在TDD中命名测试与单元测试命名

时间:2014-07-01 21:07:57

标签: c# unit-testing tdd nunit bdd

我一直在做一些使用TDD开发的测试;即先写下我的考试。

我一直习惯于使用这种命名约定来编写测试。

  MethodName_DoesWhat_WhenTheseConditions

这些非常适合单元测试,因为我知道方法名称是什么,但是做TDD我不知道方法名称。例如,我有一个说明

的用户故事
    "As a user, I can return the total number of records in the database"

现在看看这个,我马上知道我会有很多方法,层。

但是我现在还不知道TDD中这些方法的名称,所以尝试为测试名称添加前缀是否有意义?有没有人在这里有任何建议?

此外,一旦我编写了我的测试和我的方法/类,一切正常,是否有意义创建额外的"单元测试"通过TDD来测试我没有的东西?

4 个答案:

答案 0 :(得分:3)

通过关注" Outside-In"开发方法,您将发现/发展您的TDD单元测试名称作为开发过程的一部分(也请参阅此答案here

例如,记下您的用户故事(我稍作修改):

As a user
I want to know the total number of records in the database
So that I can report back to the business owner

在开发这个故事时,您可以将其分解为多种情况,例如

Given a user logs in
When they request the total number of records
Then they should be presented with the result

在这个阶段,您仍然不知道您需要哪些单元测试。但是,使用" Outside-In"开发方法,您现在将恢复为TDD技术,以实现必要的功能。

例如,您接下来将使用常规TDD方法实现登录工具。因此,您可能有一个名为的测试方法:

WhenSubmitValidCredentials_ShouldBeAuthorised

你也可以假装它直到你做到它为止#34;使用这种方法,即您可以模拟某些依赖项(例如授权机制),以便您可以专注于实现场景的关键功能。

因此,按照这种方法,您将逐步开发用户故事所需的所有功能,同时创建精确的单元测试以满足方案。

答案 1 :(得分:2)

根据您的用户故事,我的测试名称将类似于:

  • shouldGetZeroWhenTheDatabaseIsEmpty
  • shouldGetOneWhenThereIsOneRecord
  • shouldGetTwoWhenThereAreTwoRecords

测试类就像DatabaseRecordCounterTest。

答案 2 :(得分:1)

有很多方法可以测试命名,你提到的那个就是其中之一。使用方法名称进行前缀是很好的(适用于大多数情况),但是当您的单元测试跨越多种方法时(例如common add-remove or add-search combinations),您可能会遇到一些小问题。

使用TDD,您应该从用户故事开始(就像您现在一样)并相应地命名您的测试。只有然后才能实现。使用TDD,您的方法名称将由测试驱动。

  

此外,一旦我编写了我的测试和我的方法/类,一切正常,是否有意义创建额外的"单元测试"通过TDD来测试我没有的东西?

你不应该通过TDD做一件事 。这就是重点 - 您通过测试驱动您的设计和实现。您不会编写不会导致测试失败的单行代码。

答案 3 :(得分:0)

我喜欢使用我从Phil HaackErik Dietrich

中偷走的两种方法

基本上有一个基类定义了测试中的类,然后是继承的类,它们将按照它们将要测试的行为命名。然后使用详细的名称添加测试。

public class TestClassUnderTest
{
    public ClassUnderTest Target { get; set; }
    [SetUp]
    public void before_each_test()
    {
        Target = new ClassUnderTest();
    }

    // Now each behavior has its own class with the system under test available through the Target property
    public class ThisMethod : TestClassUnderTest
    {
        [Test]
        [ExpectedException(typeof(Exception))]
        public void throws_if_null_is_passed()
        {
            Assert.IsTrue(false); // make it fail at first
        }

        [Test]
        public void returns_true_if_string_is_empty()
        {
            Assert.IsTrue(false); // make it fail at first
        }
    }

    public class ThatMethod : TestClassUnderTest
    {
        [Test]
        public void returns_argument_concatenated_with_timestamp()
        {
            Assert.IsTrue(false); // make it fail at first
        }
    }
}

使用此系统,测试类名称(在此示例中为ThisMethodThatMethod)可以被抽象为您正在测试的行为方面,直到命名有意义。您可以在所需行为之后命名它,然后将行为名称重构为函数名称(如果适用),或者对其进行优化(例如,如果行为跨越多个方法,例如:InstanciatioAndInitialization带有test {{ 1}})。一个很好的奖励是所有测试都按逻辑分组到相同的上下文中,这在您的测试U​​I中呈现得非常好。