我正在尝试使用NUnit中的TestCaseSource运行多个测试。但是当我想要的时候,我很难让[SetUp]运行。
目前它按照我的要求行事,但感觉并不“正确”。所以以下是主要的测试用例代码(简化):
public class ImportTestCases
{
ImportTestCases()
{
TestData.RunTestSetup();
}
public static IEnumerable TestCases
{
get
{
//run the funciton under test...
var results = RunFunctionSubjectToTest(TestData.ImportantVar);
//get multiple results...
var allProperties =new TestCaseData(o).Returns(true)
ExpandNestedProperties(results.AllProperties)
.ToList()
.ConvertAll(o => new TestCaseData(o).Returns(true));
return allProperties;
}
}
}
[TestFixture]
public class ImportTests
{
[TestFixtureSetUp]
public void ImporTestSetup()
{
TestData.RunTestSetup();
}
[Test, TestCaseSource(typeof(ImportTestCases), nameof(ImportTestCases.TestCases))]
public bool PropertyTest(UnitTestHelper.PropInfo info)
{
return info.DoTheyMatch;
}
}
这里的问题是[SetUp]在ImportTestCases“TestCases”之前没有运行 属性“get”运行。 “ImportTestCases”的构造函数也没有运行。因此,为了确保在引用ImportVar之前运行“RunTestSetup”,我必须执行以下操作:
public static class TestData
{
private static bool HasSetUpRan = false;
private static int _importantVar;
public static int ImportantVar
{
get
{
if(!HasSetUpRan)
{
RunTestSetup();
}
return _importantVar;
}
}
public static void RunTestSetup()
{
if (HasSetUpRan)
{
return;
}
///do set up
//e.g. _importantVar = GenerateId();
//end
HasSetUpRan= true;
}
}
正如您所看到的,这可确保在返回变量之前已运行Set up。可悲的是,到目前为止,这是我设法让它工作的唯一方法。正如我所说,感觉“错误”而且过于复杂。也许我在这里过度使用testCases?或者我应该使用某种paramatised测试用例(可能吗?)。
我试图简化上面的代码,所以道歉,如果它只是没有意义我想要测试。
主要观点是否在创建TestCaseSources之前运行[Setup]?
答案 0 :(得分:3)
重点是测试用例将在加载测试时定位。因此,在调用“ TestCases ”属性后,将执行具有[TestFixtureSetUp]
属性的例程。但是,您可以在静态构造函数中执行一些设置例程。但是为了首先调用它,你需要将测试数据放在同一个类中:
[TestFixture]
public class ImportTests
{
static ImportTests()
{
//Step 1
//run your set-up routine
}
//Step 3
[Test, TestCaseSource(nameof(ImportTests.TestCases))]
public bool PropertyTest(string s) => string.IsNullOrEmpty(s);
//Step 2
public static IEnumerable TestCases => new[] {new TestCaseData("").Returns(true)};
}
答案 1 :(得分:1)
将测试方法参数设为Func<YOURParamater>
。
因此,当Nunit需要获取TestCases列表时,它将返回
Func
不是实际参数。
在测试运行时调用此Func
并获取您的参数。
Wrap只是一个将lambda返回为Func
的函数。
与Func
相反,不能将bcs lambda强制转换为对象。
如果您发现此答案不令人满意。请先说明原因,然后再对其进行评分。
public class TestCaseClass
{
public static IEnumerable Cases
{
get
{
yield return new TestCaseData(Wrap(() => 1)).SetArgDisplayNames("1");
yield return new TestCaseData(Wrap(() => 2)).SetArgDisplayNames("2");
}
}
private static Func<T> Wrap<T>(Func<T> fun)
{
return fun;
}
}
[TestCaseSource(typeof(TestCaseClass), nameof(UserTestCases.Cases))]
public bool Tests(Func<int> getInt)
{
return getInt() == 1;
}
答案 2 :(得分:0)
也许一种可能的解决方案是使您创建TestSource的方法不是静态的并添加默认构造函数。在构造函数中,您可以执行测试用例所需的所有初始化操作。您仍然可以将TestFixtureSetUp用于其他初始化内容。
[TestFixture]
public class ImportTests
{
public ImportTests()
{
//inititalize test case source
}
[TestFixtureSetUp]
public void ImporTestSetup()
{
//inititalize rest of test
}
public IEnumerable<string> Fields()
{
return new[] { "foo", "bar", "foobar" };
}
[Test]
[TestCaseSource("Fields")]
public void PropertyTest(string info)
{
// Assert
}
}
答案 3 :(得分:0)
你要做的事基本上忽略了NUnit的工作方式。考虑这个顺序:
在决定在测试用例源中做什么时,你必须要注意这个序列,我夸大了它的效果。通常,创建长寿命对象可能不是您想要做的。
还有一些说明:
在NUnit中,测试用例几乎总是参数化。如果测试没有参数化,那么它不需要一个源,但可以只是一个简单的测试,并且可以进行所有自己的初始化。
标记与测试相同的方法和某人建议的来源是一个非常大的错误 - 病态。因为测试方法和测试用例源方法的目的是完全不同的,所以我们没有把它作为错误捕获的唯一原因是几乎没有人尝试过这样做。
最好的办法是使用源返回测试可用于实例化所需对象的参数。