我看过许多文章,看过关于TDD的大量屏幕录像,但是我仍然在现实世界项目中努力使用它。我的主要问题是我不知道从哪里开始,什么测试应该是第一个。
假设我必须编写调用外部系统方法的客户端库(例如通知)。
我希望该客户端按如下方式工作

NotificationClient client = new NotificationClient("abcd1234"); // client ID
Response code = client.notifyOnEvent(Event.LIMIT_REACHED, 100); // some params of call

幕后有一些翻译和消息格式的准备工作,因此我想将其隐藏在客户端应用程序中。

我不知道从哪里开始以及如何开始。
我应该为这个库设置一些粗糙的类吗?
我应该从下面开始测试NotificationClient吗
public void testClientSendInvalidEventCommand() {
    NotificationClient client = new NotificationClient(...);
    Response code = client.notifyOnEvent(Event.WRONG_EVENT);
    assertEquals(1223, code.codeValue());
}

如果是这样的话,在这种测试中,我被迫立即编写完整的工作实现,而没有TDD声明的任何步骤。我可以在Client中模拟某些东西,但是随后我必须知道要在前一次模拟此事,因此我需要进行一些前期设计。

也许我应该从底部开始,首先测试此消息格式组件,然后在正确的客户端测试中使用它?

正确的方法是走什么路?
我们是否应该始终从头开始(如何应对这一巨大步骤)?
我们可以从任何实现所需功能的一小部分的类开始(在此示例中为Formatter)吗?

如果我知道要在哪里进行测试,对我来说要容易得多。

最佳答案

我将从这一行开始:

NotificationClient client = new NotificationClient("abcd1234"); // client ID

听起来我们需要一个NotificationClient,它需要一个客户端ID。这很容易测试。我的第一个测试可能类似于:
public void testNewClientAbcd1234HasClientId() {
    NotificationClient client = new NotificationClient("abcd1234");
    assertEquals("abcd1234", client.clientId());
}

当然,它不会首先编译-直到我编写了一个带构造函数的NotificationClient类,该构造函数采用字符串参数和返回字符串的clientId()方法-但这是TDD周期的一部分。
public class NotificationClient {
    public NotificationClient(string clientId) {
    }
    public string clientId() {
        return "";
    }
}

在这一点上,我可以运行测试并观察它是否失败(因为我已经将clientId()的返回值硬编码为一个空字符串)。单元测试失败后,我只需编写足够的生产代码(在NotificationClient中)即可通过测试:
    public string clientId() {
        return "abcd1234";
    }

现在我所有的测试都通过了,所以我可以考虑下一步该怎么做。下一步(很明显,对于来说很明显)是确保我可以创建ID并非“abcd1234”的客户端:
public void testNewClientBcde2345HasClientId() {
    NotificationClient client = new NotificationClient("bcde2345");
    assertEquals("bcde2345", client.clientId());
}

我运行测试套件,观察到testNewClientAbcd1234HasClientId()通过时,testNewClientBcde2345HasClientId()失败,现在我有充分的理由将成员变量添加到NotificationClient:
public class NotificationClient {
    private string _clientId;
    public NotificationClient(string clientId) {
        _clientId = clientId;
    }
    public string clientId() {
        return _clientId;
    }
}

假设没有打印错误,那将使我的所有测试通过,并且我可以继续进行下一步。 (在您的示例中,可能正在测试notifyOnEvent(Event.WRONG_EVENT)返回的Response等于1223的codeValue()。)

这有帮助吗?

关于unit-testing - 如何在现实世界项目中选择TDD起点?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7987372/

10-12 23:25