unit-testing - 使用 BDD 风格的 "When"命名测试类及其维护结果

标签 unit-testing junit tdd naming-conventions bdd

根据我的理解,真正的 BDD 更多的是满足业务规范,但我认为从类级别的行为开始可能是值得的,因为我正在努力采用 TDD,而 BDD 命名使它更容易。

让我们关注 BDD 风格的单元测试(在类级别)。

我开始按照建议使用“When”以反射(reflect)预期行为的方式命名我的测试类in this article .它真的很有效。然而很快,我意识到这样的测试类名称可能会产生以下维护后果。

为手头的类(class)找到测试类(class)并不容易。

我习惯了传统的命名“ClassnameTest”,在这种情况下,我可以快速找到测试类。

我使用 Java 和 JUnit4,但不幸的是我没有像给定的内置语言结构等。

让我们考虑以下示例。

public class Lion{...}

测试类
public class WhenLionIsHungy{
    @Test public void should_eat_meat(){...}
    @Test public void should_not_eat_grass(){...}
    @Test ...
}

public class WhenLionHunts{...}

public class WhenLionIsWithCubs{...}
...

请原谅我举个例子。假设它们都是有效的测试类。除非您确定我们永远不应该为目标类设置多个基于行为的测试类,否则不要担心它。

BDD 是将测试转换为文档的优雅解决方案,上面的示例反射(reflect)了这一点。毕竟,测试像“testMoneyTransfer()”这样的方法永远不会提供任何见解。

上面是一个快乐的例子,但猜测名为“LibraryServiceImpl”的类的测试类将是一场噩梦。

是 WhenBookIsRequested 或 WhenLibraryIsClosed 还是两者兼而有之?

单元测试应该作为完整或某种程度的文档。然而,在 LibraryServiceImpl 案例中,文档本身并不容易被发现。

即使您正确命名了一个类并使用 SRP 对其进行设计,仍然很难找到测试类,因为搜索引用也可能会在测试文件夹中返回 100 次点击。

我第一次尝试使用@Suite 解决问题。
@RunWith(Suite.class)
@Suite.SuiteClasses({WhenLionIsHungy.class,
                     WhenLionHunts.class,
                     WhenLionIsWithCubs.class
})
public class LionTest{}

它解决什么问题?
  • 很容易找到手头的类的测试类,因为我以目标类名命名它。
  • 一个类在一个地方的所有类型的高级行为。就个人而言,我觉得这更有见地。

  • 它介绍了什么?
  • 没有目的的空类,只是将“何时”类分组。我不完全确定这是否是一个更大的问题,但拥有它们肯定感觉很奇怪。


  • 我第二次尝试使用内部类解决问题。 Reference
    @RunWith(Enclosed.class)
    public class LionTest{
    
         public static class WhenLionIsHungy{...}
    
         public static class WhenLionHunts{...}
    
         ...
    
    }
    

    它解决什么问题?
  • 很容易找到手头的类的测试类,因为我以目标类名命名它。
  • 没有更多的空课。
  • 有点容易弄清楚类(class)的要点。 (IDE 可以提供大纲)

  • 它介绍了什么?
  • 冗长可笑的类(class)。然而,没有办法将所有这些都放在一个地方,同时又紧凑且可读。
  • 使用静态内部测试类?听起来对吗?

  • 我希望我不必完全回到在目标类之后命名测试类,而是“轻松找到手头类的测试类”。似乎是一个不容忽视的重大问题。

    请分别提供您对上述解决方案的意见。

    如果你能想出别的东西就太好了。

    最佳答案

    “我使用 Java 和 JUnit4,不幸的是我没有像给定的内置语言结构”

    如果您在 JVM 上,您可以使用 groovy/spock,将 spock 集成到 Java 项目中真的很容易,而且 IMMO 值得付出努力。试一试!。

    我不认为为具体的生产类找到测试类是您真正需要的。 BDD 的一件事是,您可以根据正在开发的功能组织测试,实现此功能的类是一个实现细节。通常,当您在寻找一些测试时,您真正在寻找是因为您想验证/检查/修复应用程序中的某些功能。

    事实上,问题是找不到 LibraryServiceImpl 的测试,这里的问题是有一个名字不好的类。 “库”这个名称中唯一的信息“ServiceImpl”是噪音。在这一点上,问题可以更改为“找到库功能的测试”,稍微好一点,但是如果您在应用程序中有很多与库相关的功能,那么这个类可能会被分成具有有意义名称的类,例如 LibraryBooksReturnPolicy 或 LibraryNewBooksRegister (只有样本,可能是坏样本,但你可以理解)。

    BDD/TDD 它不仅是一种测试技术,它还是一种驱动设计的技术,如果是优秀设计中最重要的事情之一,则为您的类找到合适的名称,您不能付出很多努力来寻找语义和很好的方法为您的测试代码命名(无论如何这是一项很好的工作),并在您的生产代码中使用诸如“service”、“manager”或“impl”之类的词命名!。

    无论如何,如果您不同意所有这些并且仍然想找到给定类的测试,您可以使用您的 IDE 并在测试文件夹中找到类的用法,并且您有一个练习这个类毫秒的测试列表和带有可导航的链接。

    关于unit-testing - 使用 BDD 风格的 "When"命名测试类及其维护结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21399421/

    相关文章:

    unit-testing - 关于如何编写对重构友好的单元 TDD 测试的技巧

    ruby-on-rails - Pluralsight RSpec 正确的方式 : Wrong Number of Arguments for expect(client. url).to eq

    python - 如何使用 Python unittest 来测试类层次结构?

    unit-testing - Redux:如何测试连接的组件?

    java - Robotium断言失败

    java - 以非包装器样式调用服务时出现 CXF 解码错误

    python - Django 测试 : DatabaseError: no such table for ManyToManyField

    asp.net - 如何编写单元测试来测试 ASP.NET Web 表单应用程序的 CSRF 漏洞?

    java - 当@Rule相互依赖时如何处理它们的排序

    c# - FakeItEasy Setup 对象未在测试方法中返回