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

8

我一直在为使用TDD开发做一些测试,即先编写我的测试。

我一直习惯像这样编写测试,使用这种命名约定。

  MethodName_DoesWhat_WhenTheseConditions

这些对于单元测试非常有用,因为我知道方法名称是什么,但在TDD时我不知道方法名称。例如,我有一个用户故事陈述:
    "As a user, I can return the total number of records in the database"

现在看一下这个,我立刻知道我将会有许多方法和层次。

但是我现在不知道在TDD中这些方法的名称,所以尝试在测试名称前缀中加上名称是否有意义呢?这里有什么建议吗?

此外,一旦我编写了我的测试、方法/类并且一切正常工作,是否有意义创建额外的“单元测试”来测试我没有通过TDD测试的类的功能?


1
这些答案中有帮助到您吗?您是否找到解决问题的方法? - Ben Smith
4个回答

6
通过遵循“从外到内”的开发方法,你将在开发过程中发现/完善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

在这个阶段,您仍然不知道需要哪些单元测试。但是,使用“从外到内”的开发方法,您现在将恢复到TDD技术以实现必要的功能。

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


```java public void testLogin() { // Test code here } ```
WhenSubmitValidCredentials_ShouldBeAuthorised

你也可以使用这种方法来“假装你已经成功了”,即你可以模拟某些依赖项(例如授权机制),以便你可以专注于实现场景的关键功能。
因此,按照这种方法,您将逐步开发所需的所有用户故事功能,同时创建确切的单元测试以满足场景要求。

3

根据您的用户故事,我的测试名称应该是:

  • 当数据库为空时应该得到零
  • 当有一条记录时应该得到一
  • 当有两条记录时应该得到二

测试类的名称应该是DatabaseRecordCounterTest。


1

有许多测试命名的方法,你提到的是其中之一。使用方法名称作为前缀很好(适用于大多数情况),但当你的单元测试涉及多个方法时可能会遇到一些小问题(例如常见的添加-删除添加-搜索组合)。

在TDD中,你应该从用户故事开始(就像现在做的一样),并相应地命名你的测试。然后才进行实现。在TDD中,你的方法名称将由测试驱动。

此外,一旦我编写了我的测试、方法/类,并且一切都正常工作,是否有意义创建额外的“单元测试”来测试我没有通过TDD测试的类的其他内容?

你不应该有任何一个东西是没有通过TDD完成的。这就是整个意义——你通过测试来推动你的设计和实现。你不会编写任何一行代码,它不起源于失败的测试。


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与测试initialization_must_be_called_before_any_other_calls_to_the_system)。一个很好的奖励是,所有测试逻辑上分组在同一上下文中,在您的测试UI中呈现得很好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接