比方说,我有两种搜索算法的实现,它们为相同的输入返回相同的结果。他们都实现相同的接口。针对不同实现的相同单元测试
如何使用单个[TestClass]
来测试两个实现,而不是使用最终相同的逻辑创建两个测试文件?
我可以告诉MSUnit使用不同的构造函数参数两次启动其中一个测试吗?
也许我应该(n)以某种方式注入它?
比方说,我有两种搜索算法的实现,它们为相同的输入返回相同的结果。他们都实现相同的接口。针对不同实现的相同单元测试
如何使用单个[TestClass]
来测试两个实现,而不是使用最终相同的逻辑创建两个测试文件?
我可以告诉MSUnit使用不同的构造函数参数两次启动其中一个测试吗?
也许我应该(n)以某种方式注入它?
[TestClass]
public abstract class SearchTests
{
private ISearcher _searcherUnderTest;
[TestSetup]
public void Setup()
{
_searcherUnderTest = CreateSearcher();
}
protected abstract ISearcher CreateSearcher();
[TestMethod]
public void Test1(){/*do stuff to _searcherUnderTest*/ }
// more tests...
[TestClass]
public class CoolSearcherTests : SearcherTests
{
protected override ISearcher CreateSearcher()
{
return new CoolSearcher();
}
}
[TestClass]
public class LameSearcherTests : SearcherTests
{
protected override ISearcher CreateSearcher()
{
return new LameSearcher();
}
}
}
这是唯一的好方案。 – 2013-04-03 10:20:58
我宁愿有两个不同的[TestMethod]
在一个[TestClass]
每个测试只有一个实现:这种方式失败的测试将总是正确地指出哪个实现出错。
如果您使用NUnit,你可以通过在属性 http://www.nunit.org/index.php?p=testCase&r=2.5.6
声明的变量,如果你使用类似:
[TestCase(1)]
[TestCase(2)]
public void Test(int algorithm)
{
//..dostuff
}
如果将1 2运行一次,一次,用途相同的安装/拆卸太:)
没有在MSTest的等效但您可以在一定程度捏造了在这里解释: Does MSTest have an equivalent to NUnit's TestCase?
你已经用NUnit
标记了你的问题,但你问了关于MSTest
。你在NUnit中使用参数化测试装置可以获得什么。我不熟悉MSTest在那里建议一个等效的方法,并且快速搜索表明MSTest可能没有此功能。
在NUnit中,您可以通过将多个[TestFixture(...)]
属性应用于具有不同参数的夹具类来参数化测试夹具。这些参数将传递给灯具构造函数。
由于可传递参数的类型有限制,因此您可能需要在指定算法时传递一个字符串,然后在构造函数中将提供搜索算法的委托或对象分配给成员字段用于测试。
例如:
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace MyTests
{
public static class SearchAlgorithms
{
public static int DefaultSearch(int target, IList<int> data)
{
return data.IndexOf(target);
}
public static int BrokenSearch(int target, IList<int> data)
{
return 789;
}
}
[TestFixture("forward")]
[TestFixture("broken")]
public class SearchTests
{
private Func<int, IList<int>, int> searchMethod;
public SearchTests(string algorithmName)
{
if (algorithmName == "forward")
{
this.searchMethod = SearchAlgorithms.DefaultSearch;
return;
}
if (algorithmName == "broken")
{
this.searchMethod = SearchAlgorithms.BrokenSearch;
}
}
[Test]
public void SearchFindsCorrectIndex()
{
Assert.AreEqual(
1, this.searchMethod(2, new List<int> { 1, 2, 3 }));
}
[Test]
public void SearchReturnsMinusOneWhenTargetNotPresent()
{
Assert.AreEqual(
-1, this.searchMethod(4, new List<int> { 1, 2, 3 }));
}
}
}
我不能说我用这个方法非常高兴,但这里是我落得这样做。然后我去寻找更好的方法并找到了这个问题。这种方法符合标准:1)我正在使用MS Test,2)我只写了一次测试逻辑,3)我可以判断哪个实现失败(并且双击测试将使我到正确的测试类) 。 该方法使用一个基类来包含所有实际的测试逻辑,然后为每个实现(我有3个)的派生类设置基础接口上的特定实现并覆盖基本测试方法。
[TestClass]
public abstract class SearchTestBase
{
protected ISearcher Searcher { get; set; }
[TestMethod]
public virtual void Find_Results_Correct()
{
// Arrange (code here)
// Act (single line here)
var actual = Searcher.Results(input);
// Assert
}
}
(different file...)
[TestClass]
public class FastSearcherTest : SearcherTestBase
{
[TestInitialize]
public void TestInitialize()
{
Searcher = new FastSearcher();
}
[TestMethod]
public override void Find_Results_Correct()
{
base.Find_Results_Correct();
}
}
(different file...)
[TestClass]
public class ThoroughSearcherTest : SearcherTestBase
{
[TestInitialize]
public void TestInitialize()
{
Searcher = new ThoroughSearcher();
}
[TestMethod]
public override void Find_Results_Correct()
{
base.Find_Results_Correct();
}
}
所以我不喜欢这种做法是,每次我想添加一个测试,我需要去每个测试文件并覆盖新的测试方法。我喜欢的是你的3个要求。如果我需要更改测试,我只在一个地方改变逻辑。 我看到这个解决方案优于两个测试所称的单个方法的优点是,我不必重复设置正确实现的代码。在这个解决方案中,你有一行调用base.TestName()的单行,而不是两行,一行设置Searcher,另一行调用测试。 Visual Studio也使得编写速度更快......我只需键入“覆盖”并获取选项列表。自动完成为我写剩下的部分。
说明基于我的测试。
接受的答案(使用抽象类)只要工作,抽象类和具体类在同一个程序集中。
如果您希望在不同程序集中使用抽象类和具体类,那么KarlZ提到的方法不幸似乎是必需的。不知道为什么会这样。在这种情况下,TestExplorer将不会显示TestMethod。
此外,接受的答案使用嵌套在抽象类中的具体类。这似乎不是一个要求。
使用MSTestV2(1.1.17),VS2017进行测试。 以下是使用的示例类。
Assembly 1
[TestClass]
public abstract class SampleExternal
{
[TestMethod]
public void SampleTest01()
{
Assert.IsTrue(false, this.GetType().Name);
}
}
Assembly 2
[TestClass]
public abstract class Sample
{
[TestMethod]
public void SampleTest01()
{
Assert.IsTrue(false, this.GetType().Name);
}
[TestClass]
public class SampleA : Sample
{
}
}
[TestClass]
public class SampleB : Sample
{
}
[TestClass]
public class SampleC : SampleExternal
{
}
[TestClass]
public class SampleD : SampleExternal
{
}
使用这些时,测试SampleA和SampleB将执行(和设计失败),但SampleC &采样不会。
在你的问题中,你询问MSTest,但是在你的标签中你指定了NUnit。你想要哪一个答案? – 2013-03-22 12:42:24