我有一个包含程序集的文件夹,它们都包含某个接口的实现(在每个程序集中都不同)。我已经为该接口编写了一些单元测试,并希望自动完成在每个实现上运行接口测试的任务。
我有一个我不喜欢的工作解决方案:
在实际测试类中编写代码以加载(程序集)并实例化实现,将它们存储在列表中。
编写每个测试以遍历实现列表,在每个测试上运行其断言。
我想要的是是在一个实现上运行所有测试,然后继续下一个再次运行所有测试,依此类推。我的想法是找到一种方法来做(像程序):
(我意识到我可以在文件系统中乱扔文件 - 比如将程序集放在一个位置>运行测试,加载一个实现>用下一个实现替换程序集,然后重复这个过程。但是,如果可能的话,我想要一些不那么粗糙的东西。)
我一直在关注nUnit测试跑步者(控制台等)的捷径,但到目前为止还没有找到。有没有人知道是否有办法使用nUnit或任何其他可编程控制的测试套件来实现我想要的东西?或者也许还有另一种方式来实现这一切,这将满足我想要的"我想要的"以上标准?
答案 0 :(得分:0)
我最终使用了NUnit SuiteAttribute。
这种方法涉及创建一个“伞类”,如下所示:
namespace Validator {
public class AllTests {
[Suite]
public static IEnumerable Suite {
get {
var directory = @"[ImplementationAssembliesPath]";
var suite = new ArrayList();
// GetInstances is a method responsible for loading the
// assemblys and instantiating the implementations to be tested.
foreach (var instance in GetInstances(directory)) {
suite.Add(GetResolvedTest(instance));
}
return suite;
}
}
// This part is crucial - this is where I get to inject the
// implementations to the test.
private static Object GetResolvedTest(ICalculator instance) {
return new CalculatorTests {Calculator = instance};
}
[...]
}
请注意,测试类具有注入我想要的实现的属性。我选择了属性注入,因为测试运行者通常不喜欢默认构造函数。但是,我必须从实际测试类中删除TestFixtureAttribute
(此处省略),以免混淆Console-Runner运行的内容。
然后我创建了一个简单的控制台应用程序来运行带有/fixture
参数的NUnit Console-Runner:
namespace TestRunner {
using System;
using NUnit.ConsoleRunner;
internal class Program {
private static void Main(String[] args) {
var testDllPath = @"[TestAssemblyPath]/Validator.dll";
var processArgument = @"/process=Separate";
var domainArgument = @"/domain=Multiple";
var runtimeArgument = @"/framework=4.5";
var shadowArgument = @"/noshadow";
var fixtureArgument = String.Format(@"/fixture={0}", "[Namespace].AllTests");
Runner.Main(new[] {
testDllPath,
processArgument,
domainArgument,
runtimeArgument,
shadowArgument,
fixtureArgument
});
Console.ReadLine();
}
}
}
我仍然有兴趣听取您对此以及替代解决方案的意见。
答案 1 :(得分:-1)
如果你想测试一组固定的组件,你不必做像移动组件或指导测试跑步者这样的花哨的东西。
与普通类一样,您可以为单元测试类使用继承。我建议你创建一个抽象基类,它可以用来测试这个接口的实现。对于接口的每个实现,您可以创建一个继承自基类的新类。
基类看起来像这样:
public class BaseMyInterfaceImplementationTest
{
protected MyInterface ClassUnderTest;
//Add your tests here with the [Test] attribute:
[Test]
public void TestScenario1()
{
//do your test on ClassUnderTest
}
}
派生类如下:
[TestFixture]
public class Implementation1Tests : BaseMyInterfaceImplementationTest
{
[SetUp]
public void BaseTestInitialize()
{
ClassUnderTest = new Implementation1();
}
}