C# 组织单元测试:班级还是行为?从哪里开始?
摘要 我编写了一个C# 组织单元测试:班级还是行为?从哪里开始?,c#,unit-testing,organization,code-organization,C#,Unit Testing,Organization,Code Organization,摘要 我编写了一个RandomValues类,它提供了多种方法来生成每种值类型的随机值。该静态类应稍后用作单元测试其他项目类的工具 我以TDD的方式对每个方法进行了单元测试 现在,我看到可能会有一些重构来促进代码重用,这让我在搜索了互联网上不同类型的结果后提出了这个问题。其中,有一个保持着我的注意力 除此之外,我真的很喜欢以如下行为方式构建单元测试: 现在,我想知道如何将此应用到我的案例中 RandomValuesTests 进一步思考 我曾想过使用一个基类来组织我的测试,该基类将提供两个抽
RandomValues
类,它提供了多种方法来生成每种值类型的随机值。该静态类应稍后用作单元测试其他项目类的工具
我以TDD的方式对每个方法进行了单元测试
现在,我看到可能会有一些重构来促进代码重用,这让我在搜索了互联网上不同类型的结果后提出了这个问题。其中,有一个保持着我的注意力
除此之外,我真的很喜欢以如下行为方式构建单元测试:
现在,我想知道如何将此应用到我的案例中
RandomValuesTests
进一步思考
我曾想过使用一个基类来组织我的测试,该基类将提供两个抽象方法:ReturnsRandomValues
和returnsinrangerangerandomvalues
,并按类型创建一个测试类,覆盖这两个方法,如下所示
RandomValuesTestBase
公共抽象类RandomValuesTestBase其中T:IComparable{
公共摘要void ReturnsRandomValues();
公共抽象void返回sinRangeRandomValues(T最小值,T最大值);
}
[测试夹具]
公共类RandomInt:RandomValuesTestBase{
[测试]
public override void ReturnsRandomValues(){
//对RandomInt_返回使用如上所示的相同代码。。。
}
[测试用例(10,20)]
公共重写void ReturnsInRangeRandomValues(int-minValue,int-maxValue){
//对RandomInt_ReturnsInRange使用如上所示的相同代码。。。
}
}
但是,我必须为每个类型创建一个测试类:bool
,byte
,char
这听起来一点也不好
我现在正试图找出如何从总结中提到的两个参考文献开始,并从中创建一个可行的组织
或者,我保留了以前的简单方式,即在这个类中每个类都有一个测试文件…我个人不会担心在这里让您的测试变得通用或抽象。我认为,
RandomValues
类支持的每种类型都需要自己的测试集,并且可能会以不同的方式实现
我认为重要的部分是,
RandomValues
类的功能是使用测试优先的方法实现的。首先编写随机整数的测试,然后编写日期时间,依此类推。我认为你所写的测试简单、清晰、易懂。+1并接受了你的答案,因为你完美地回答了我的问题。除此之外,我想知道一个更复杂的情况是最佳实践方面的最佳做法。
[TestFixture]
public class RandomValuesTest {
[Test]
public void RandomInt_ReturnsRandomIntegerValues() {
int unexpected = RandomValues.RandomInt();
int actual = RandomValues.RandomInt();
Assert.AreNotEqual(unexpected, actual);
}
[Test]
public void RandomInt_ReturnsInRangeIntegerValues() {
int minValue = 12;
int maxValue = 20;
int actual = RandomValues.RandomInt(minValue, maxValue);
Assert.IsTrue(minValue <= actual && actual <= maxValue);
}
[Test]
public void RandomDateTime_ReturnsRandomDateTimeValues() {
DateTime unexpected = RandomValues.RandomDateTime();
DateTime actual = RandomValues.RandomDateTime();
Assert.AreNotEqual(unexpected, actual);
}
[Test]
public void RandomDateTime_ReturnsInRangeIntegerValues() {
DateTime minValue = new DateTime(2000, 1, 1);
DateTime maxValue = new DateTime(2000, 12, 31);
DateTime actual = RandomValues.RandomDateTime(minValue, maxValue);
Assert.IsTrue(minValue <= actual && actual <= maxValue);
}
[Test]
public void RandomEnum_ReturnsRandomEnumValues() {
RandomValuesEnum unexpected = RandomValues.RandomEnum<RandomValuesEnum>();
RandomValuesEnum actual = RandomValues.RandomEnum<RandomValuesEnum>();
Assert.AreNotEqual(unexpected, actual);
}
}
public static class RandomValues {
public static int RandomInt() { return RandomInt(int.MinValue, int.MAxValue); }
public static int RandomInt(int minValue, int maxValue) {
return generator.Next(minValue, maxValue);
}
// And the other Random[Type] here...
private static Random generator = new Random();
}
public abstract class RandomValuesTestBase<T> where T : IComparable<T> {
public abstract void ReturnsRandomValues();
public abstract void ReturnsInRangeRandomValues(T minValue, T maxValue);
}
[TestFixture]
public class RandomInt : RandomValuesTestBase<int> {
[Test]
public override void ReturnsRandomValues() {
// Use the same code as shown above for RandomInt_Returns...
}
[TestCase(10, 20)]
public override void ReturnsInRangeRandomValues(int minValue, int maxValue) {
// Use the same code as shown above for RandomInt_ReturnsInRange...
}