可以在Visual 2008中为单元测试创建一个通用抽象基类吗?
如果基础抽象测试类是而不是泛型,则其所有标记为[TestMethod]
的基本方法都在派生类中正确继承,并在Visual中执行。如果基类是泛型,则Visual不会在派生类中执行这些方法。
假设您有一堆实现此接口的解析器类(简化):
// parses the input stream into an
// instance of T
interface IParser<T>
{
IParserResult<T> Parse(byte[] input);
}
想象一下,您有一组解析器,它们可以解析某个流:
class HeaderParser : IParser<T> { ... }
class SomeOtherParser : IParser<T> { ... }
... many more ...
为了测试每个解析器的功能,可以将常见的测试模式提取到这样的抽象类中:
[TestClass]
abstract class ParserTest<T>
{
[TestMethod]
public void TestParser()
{
// 1. init parser
var parser = new T();
// 2. get data
var input = GetInputData();
// 3. parse
var result = parser.Parse(input);
// 4. make common assertions
Assert.AreEqual(ParserResultType.Success, result.Type);
Assert.AreEqual(input.Length, result.NextDataOffset);
// 5. specific validation
Validate(result.Value);
}
protected abstract byte[] GetInputData();
protected abstract void Validate(T result);
}
如果这个类是泛型的和抽象的,那么TestParser
方法将不会作为派生类的单元测试来执行。
发布于 2011-07-15 09:38:25
好的,我选择了一种不同的方法,类似于@stijn不久前的建议。
我完全删除了抽象基类,并创建了一个从实际解析器测试中调用的助手类。这是一个更好的解决方案,因为它允许在每个派生类中用不同的参数和验证方法组合重用相同的方法(而抽象类只有一对CreateData/TestResults抽象方法)。
public class ParserTestHelper
{
public static void Test<T>(
Func<IParser<T>> getParser,
Func<byte[]> getInput,
Action<T> checkResult)
{
// get parser
var parser = getParser();
// get input data
var input = getInput();
// parse
var result = parser.Parse(input, 0);
// common assertions
Assert.AreEqual(ParserResultType.Success, result.ResultType);
Assert.AreEqual(input.Length, result.NextDataOffset);
// validate results
checkResult(result.ParsedValue);
}
}
派生类现在可以简单地调用实际测试方法中的方法:
[TestClass]
public class HeaderParserTest
{
[TestMethod]
public void TestHeader()
{
ParserTestHelper.Test(
() => new HeaderParser(),
() => /* generate data */,
() => /* validate results */);
}
}
谢谢大家!
发布于 2011-07-15 08:46:55
我同意史提恩对你问题的评论。我更喜欢一个对象的所有测试都集中在一个固定设备中。此外,如果将测试保存在抽象类中,这意味着您正在一次又一次地测试相同的功能。这充其量是多余的重复;在最坏的情况下,读者会感到困惑。最后,您的需求表明您的测试对象可能需要一个公共的抽象基类。如果是这种情况,则应该分别测试基类,并测试每个派生类,而不测试基类的功能。
尽管如此,我有时使用基类进行设置和删除,以避免一次又一次地做相同的事情。对于我来说,最常见的情况是,在能够使用SDK之前,我必须启动许可证。尽管如此,我仍然没有完全相信这是一种很好的方法。
https://stackoverflow.com/questions/6704172
复制相似问题