C# 单元测试-相关测试

C# 单元测试-相关测试,c#,.net,visual-studio-2008,unit-testing,C#,.net,Visual Studio 2008,Unit Testing,我正在创建一个相互依赖的单元测试列表。例如,我的第一个测试在数据库中创建一条记录,并检查返回值是否大于0 然后,第二个测试检查在第一个测试中创建的记录的数据。但是,它需要在第一次测试中生成的记录的ID 最初,我在第一个测试中调用了第二个测试,这样我就可以通过ID作为参数,它工作得很好,只是这意味着基本上只有一个测试 我创建了一个有序列表,其ID声明在范围之外,但在第一次单元测试之后,该值返回到0,因此显然第二次单元测试失败 有没有办法创建测试,以便它们共享第一次测试中产生的值 代码如下: [Te

我正在创建一个相互依赖的单元测试列表。例如,我的第一个测试在数据库中创建一条记录,并检查返回值是否大于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();
    }
}

这很顽皮,但是您可以取消注释(如果是由测试向导或add创建的)

这与模拟一些常见的测试数据没有什么不同,尽管同样可疑

我正在创建一个相互依赖的单元测试列表。例如,我的第一个测试在数据库中创建一条记录,并检查返回值是否大于0

在我看来,这种做法是不正确的。你可能会创造邪恶的代码,这会反过来咬你。此类代码:

  • 打破了单元测试的原则
  • 很难维持
  • 非常死板、繁琐且容易出错
单元测试必须是独立的,否则就不要编写它们。原因是随着软件复杂性的增加,测试的复杂性也会增加。如果您有一个测试依赖于其他测试,那么维护测试将成为一种负担。因此,软件的成本增加了,但代码的质量却没有增加。如果测试之间没有依赖关系,那么软件的复杂性并不重要,因为您可以单独测试每个单独的功能

另一个优点是可以并行运行测试。对于大型系统,重要的是持续集成(和部署)周期要快。通过并行运行测试,您可以显著加快发布周期

建议的解决方案


您试图完成的可能是集成测试。编写它们的一种方法是为此类测试创建一个单独的项目。每个测试仍然相互独立,但可能每个测试都需要一些NUnit测试术语中的
设置
拆卸
。因此,安装程序将准备集成测试通过所需的一切,而拆卸将在每次测试后执行清理

你不应该那样做。每个测试都应该是独立的。你甚至不知道测试运行者执行测试的顺序,他们没有顺序!错。您的第二个单元测试可以在第一个单元测试执行之前执行,因此根本没有创建任何记录。一个自包含的单元测试在设置中创建自己的测试数据,并在拆卸过程中进行清理,但这并不能保证。一些测试运行者甚至故意对测试进行洗牌,以确保测试之间不相互依赖。很抱歉,您使用单元测试的方式是错误的。@user1016253我对此表示赞赏。问题是,客户可能会认为它没有业务价值,并可能在确定优先级时将其丢弃(假设XP的规划游戏)。用Bob Martin的话来说,专业人士总是保持代码的整洁,因为这是保持可持续发展的唯一途径。现在回想起来……哇,我真的不理解单元测试。你能证明“单元测试必须是独立的”这句话是正确的吗?似乎是常识,但我从来没有真正听到过这样做的原因…@101只是增加了几段:基本上,它降低了测试的复杂性。你希望测试尽可能简单,这样你就不会浪费脑力去理解测试了。这是大型系统中的一个大问题。作为奖励,您可以并行运行测试,从而加快测试时间。在实践中,我看到测试运行速度提高了2到8倍。如果是5分钟对40分钟,并且你在每次提交后释放,那么这是有意义的。
//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()
{
}