我正在创建一个相互依赖的单元测试列表。例如,我的第一个测试在数据库中创建一个记录,并检查返回值是否大于0.
然后第二个测试检查在第一个测试中创建的记录的数据。但是,它需要在第一次测试中生成的记录的ID。
最初我在第一次测试中调用了第二个测试,这样我就可以将ID作为参数传递,这很好用,除非这意味着基本上只有一个测试。
我创建了一个有序列表,其ID在范围之外声明,但在第一次单元测试之后,该值返回0,显然第二次单元测试失败。
有没有办法创建测试,以便它们共享第一次测试中产生的值?
代码如下:
[TestMethod]
public void TestNewLandlord_InsertIntoImportFiles_ReturnFileID()
{
try
{
DataSet ds = EngineBllUtility.InsertIntoImportFiles(connString, @"C:\Documents and Settings\dTrunley\My Documents", "HFISNewLandlordTest.csv",
"TestNewLandlord()", WindowsIdentity.GetCurrent().Name, "HFIS Landlords", "NA", 30247531, false);
importFileId = long.Parse(ds.Tables[0].Rows[0]["ImportFileID"].ToString());
Assert.IsTrue(importFileId > 0);
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
}
}
[TestMethod]
public void TestNewLandlord_InsertIntoImportFiles_CorrectData()
{
try
{
using (SqlConnection connectionString = new SqlConnection(connString))
{
using (SqlCommand sqlCommand = new SqlCommand(
String.Format("SELECT * FROM [mydeposits].[import].[ImportFiles] WHERE [ImportFileID] = {0}", importFileId), connectionString))
{
connectionString.Open();
using (SqlDataReader dr = sqlCommand.ExecuteReader())
{
if (dr.HasRows)
{
bool correctData = true;
dr.Read();
if (!dr["ImportFileStatusID"].ToString().Equals("1"))
correctData = false;
if (!dr["HeadOfficeMemberID"].ToString().Equals("247531"))
correctData = false;
Assert.IsTrue(correctData);
TestCleanup();
}
else
throw new Exception("Import does not exist in database");
}
}
}
}
catch (Exception ex)
{
Assert.Fail(ex.Message);
TestCleanup();
}
}
答案 0 :(得分:5)
我正在创建一个相互依赖的单元测试列表。例如,我的第一个测试在数据库中创建一个记录,并检查返回值是否大于0.
在我看来,这种做法是不正确的。你可能会制造出会让你反感的邪恶代码。这样的代码:
单元测试必须独立,否则根本不要写它们。原因在于软件的复杂性增加 - 测试的复杂性也随之增加。如果你有一个测试取决于其他人维护测试成为负担。因此,软件的成本增加,但代码的质量却没有。如果您在测试之间没有依赖关系 - 软件的复杂性并不重要,因为您可以单独测试每个单独的功能。
另一个优点是您可以并行运行测试。对于大型系统,持续集成(和部署)周期很快很重要。通过并行运行测试,您可以显着加快发布周期。
建议的解决方案
您要完成的任务可能是集成测试。编写它们的一种方法是为这些测试创建一个单独的项目。每个测试仍然是彼此独立的,但是在NUnit测试术语中,每个测试可能需要一些SetUp
和TearDown
。因此,SetUp将准备集成测试所需的所有内容,TearDown将在每次测试后执行清理。
答案 1 :(得分:3)
这非常顽皮,但你可以不发表评论(如果由测试向导创建或添加)
//You can use the following additional attributes as you write your tests:
//Use ClassInitialize to run code before running the first test in the class
[ClassInitialize()]
public static void MyClassInitialize(TestContext testContext)
{
}
//Use ClassCleanup to run code after all tests in a class have run
[ClassCleanup()]
public static void MyClassCleanup()
{
}
//Use TestInitialize to run code before running each test
[TestInitialize()]
public void MyTestInitialize()
{
}
//Use TestCleanup to run code after each test has run
[TestCleanup()]
public void MyTestCleanup()
{
}
模仿一些常见的测试数据并没有什么不同,尽管同样可疑。