我目前正在尝试第一次学习NUnit。
对于我想使用TDD开发的C#程序,我决定要编写一个User
类。这个User
类(看起来)将像这样:
using System;
namespace SSH_file_drop
{
public class User
{
private Boolean authenticated = false;
public string userName = null;
//one-time object 'transmission' instance to allow single-use file transmission field
Transmission fileVehicle = null;
//property to discern whether user has been correctly authenticated
public Boolean isAuthenticated
{
get;
}
public Boolean canSend ()
{
if (authenticated)
{
return this.userType != "sender";
}
return false;
}
public User(String inputUName)
{
String userName = inputUName;
}
public static void generateUser(string userName)
{
//contact server to attempt to register new user
}
public void ChangePassword(String oldPassword, String newPassword)
{
//ask server to change user password
}
public Boolean SetUpTransmission()
{
if (canSend())
{
try
{
fileVehicle = new Transmission(this);
return true;
}
catch (e)
{
//write exception message
return false;
}
}
else
{
return false;
}
}
}
}
此刻仅占位符代码。
但是为了测试User
类,我试图编写一个TestFixture来创建User类的单独实例,并以某种方式持久存储它们直到拆解,并对每个对象执行相同的测试。
我的想法是创建一个User
对象数组作为TestCase数据源,以通过[Order(<n>)]
属性(bar User实例初始化测试方法)按顺序测试所有内容,但是我读过{{ 3}},它将在运行时为其中的每个方法创建一个TestFixture的新实例,因此我将无法以这种方式修改Test Fixture中的持久数据。
由于我正在尝试实现状态逻辑-User
对象isAuthenticated()(并且此身份验证依赖于此后的后续测试,因为所有用户数据都被建模为存储在远程数据库中),是否存在一种方法,而无需通过重复操作(创建对象,身份验证,检查userType等)创建测试,从而进行多个声明?
答案 0 :(得分:1)
回答问题中与NUnit的工作方式有关的部分...
关于NUnit中的夹具实例的生存期,您所引用的答案具有误导性,并且有点令人惊讶,因为这没有太大的奥秘!
NUnit V2的主要开发者Jim Newkirk的话只是他希望自己完成NUnit V2的一种陈述。他在xUnit.net框架中实现了这些想法,但与NUnit 3无关。
与NUnit V2一样,NUnit 3创建TestFixture
的单个实例,该实例用于所有测试。您可以使用[OneTimeSetUp]
创建要在测试中使用的对象,并将它们存储为类的成员。如果这些对象是有状态的,则应避免对使用它们的夹具中的测试使用并行测试执行。
如果需要额外的每次测试设置,则可以使用[SetUp]
来实现此目的,并使用[TearDown]
删除可能对后续测试产生负面影响的所有更改。
您还可以指定测试的顺序,但这通常不是一个好主意,因为一个损坏的测试可能会导致随后的测试也损坏。如果可以,请尝试使每个测试独立。
还请注意,如果您希望能够针对各种类型的对象多次运行相同的灯具,则参数化的灯具是一个不错的选择。只需向构造函数传递足够的信息,以便可以在一次性设置中完成正确的对象初始化。
请务必在文档中阅读以上所有内容的详细信息:https://github.com/nunit/docs/wiki
答案 1 :(得分:0)
在这种情况下,我们采用的方法是创建帮助程序方法,以适当的状态制造被测类的实例。
这实际上是您提到的方法,只是方法略有不同。
建议的方法要考虑的其他问题(我建议该方法应避免的)是有序和/或并行执行测试:如果您有一系列有状态对象,则测试将无法可靠运行并行或无序。
请注意,为了完全支持这种测试开发模式,您可能需要引入仅测试方法和。或构造函数。
例如,类中的IsAuthenticated是只读属性。为了模拟此属性的开启或关闭状态,您可能需要引入仅测试的构造函数(我倾向于避免这种方法,因为即使您已经证明它仅用于测试,也有人会在某个时候使用它)或更改实现该属性并添加一个setter方法。
如果将Authenticated属性更改为使用后备存储成员,则可以添加仅测试方法(尽管其他开发人员可能会使用此方法,但如果命名正确,它会变得更多。比构造函数更明显)。
private bool m_IsAuthenticated;
public bool IsAuthenticated {
get {
return m_IsAuthenticated;
}
}
public void Set_IsAuthenticated_ForTestONLY(bool value) {
m_IsAuthenticated = value;
}