测试驱动开发 - 如何在没有实现代码存在之前编写测试

时间:2013-12-25 03:21:07

标签: java unit-testing junit tdd

我正在学习TDD,但很难采用它,因为它并不简单。

我无法回答的问题是“如何在任何实施代码存在之前编写测试?”。

如果我们的目标类/目标方法/目标参数类型/目标返回类型不存在,

  • 在测试中编写代码时我们指的是什么。我们如何开始编写测试?
  • 如果我们所能编写的只是实际实现代码之前的测试方法名称,那么测试如何失败?

每个人都告诉为什么,但不是如何

我已尽力找到资源,详细说明在生产代码之前编写测试但是,假设我错过了良好的资源,其中大多数都充满了陈词滥调 解释为什么TTD比关注采用它的做法更重要。

用例示例。

我们假设我们正在为大学开发软件,我们的用例是课程注册。

为了简单起见,让我们将讨论局限于

  • 场景:“学生每学期最多可以注册3门课程”
  • 测试服务层和dao层。

伪代码

ENROLL(studentId, courseId)
    //check if student enrolled in less than 3 courses in the same semester as given courseId belongs in.
    //if yes, enroll him/her.
    //if not, return an error.

上面的实际实现可能涉及几个涉及服务,daos等的类。

请问您能解释一下如何逐步测试 - 开发它吗?如果您使用TDD实现这一点,您是如何逐步完成的。

我希望这可以帮助像我这样的许多挣扎。

4 个答案:

答案 0 :(得分:43)

在与EnrollingService相同的包中的src / test / java中创建EnrollingServiceTest类

class EnrollingServiceTest {
    private EnrollingService enrollingService;

    @Before 
    public void init() {
           enrollingService = new EnrollingService();
    }

    @Test
    public void testEnroll() {
           boolean result = enrollingService.enroll(1l, 1l);
           assertTrue(result);
    ...

IDE(我假设您使用的是IDE)显示错误 - EnrollingService不存在。

将光标指向EnrollService - IDE将提供创建类 - 让它在src / main / java中创建

现在IDE说缺少注册(长,长)方法 - 让IDE为你创建它。

现在IDE显示没有错误。运行测试 - 它失败了。转到注册并开始实施逻辑

等等......

答案 1 :(得分:4)

当您专注于代码的预期行为而不是代码的实现时,这将变得更加清晰。因此,根据您概述的方案,您可能会得出结论,您必须在某个类中编写enroll()方法。然后,您可以考虑如何测试此课程。

首先考虑班级的条件和对班级的期望。也许你可以识别出类的某些不变量。在这种情况下,为了测试该类,您可以考虑违反该不变量的方式。

所以接受声明:学生每学期最多可以注册3门课程,你可以考虑这种方法。

  1. 学生在指定学期注册0门课程,尝试注册课程,结果:注册成功;学生现在注册了为期一学期的1门课程。
  2. 学生在指定学期注册1门课程,尝试注册课程,结果:注册成功;学生现在注册了两个学期的学期。
  3. 学生在指定学期注册3门课程,尝试注册课程,结果:失败(可能会抛出异常?)
  4. 等等
  5. 接下来你实际上写了这些测试。这些中的每一个都可以是测试方法。因此,测试方法将确保创建对象并按预期设置环境。然后调用方法并将结果与​​预期结果进行比较。如果您预期发生的事实确实发生,那么测试就通过了。

    现在,最初,因为你还没有编写方法,测试实际上不会通过。但是当您开始编写代码时,您的测试将开始通过,最终100%的测试将通过,此时您对代码满足要求感到满意。

答案 2 :(得分:3)

public void shouldNotEnrollInMoreThanFourClassesInASemester() {
  Enroller enroller = new Enroller();
  Student student = new Student();
  Semester one = new Semester();
  Semester two = new Semester();
  Course geology = new Course(one);
  Course architecture = new Course(one);
  Course calculus = new Course(one);
  Course sociology = new Course(one);
  Course geometry = new Course(two);

  assertOk(enroller.enroll(student, geology));
  assertOk(enroller.enroll(student, architecture));
  assertOk(enroller.enroll(student, calculus));
  assertNotOk(enroller.enroll(student, sociology));
  assertOk(enroller.enroll(student, geometry));
}

答案 3 :(得分:1)

在您的场景中,您应该单独测试每个图层,以便在测试服务图层时模拟dao。

当您第一次编写测试时,它将无法编译,这意味着它会失败,但这样就没有了,因为这些类不存在。

在你的例子中哪一层应该强制注册最多3门课程?这将影响你的测试方式。

首先编写测试将帮助您解决这些类型的问题。

正如前面提到的那样,对于一个明确的答案来说,这是太开放的了,但如果你开始编写测试,那么发布更新可能有所帮助。

所以,编写你的dao测试,然后编写类和方法,以便编译,但它仍然应该失败,直到yiu完成实现。您可能希望测试2,3,4个类注册并确保每个注册失败,然后完成实现。