集成测试,但多少?

rle*_*ndi 6 java testing integration-testing automated-tests unit-testing

我团队最近的辩论让我很奇怪.基本主题是我们在功能/集成测试中应该涵盖多少以及它们应该包含哪些内容(当然,它们并不相同,但是这个示例在无关紧要的情况下是虚拟的).

假设您有一个"控制器"类,如下所示:

public class SomeController {
    @Autowired Validator val;
    @Autowired DataAccess da;
    @Autowired SomeTransformer tr;
    @Autowired Calculator calc;

    public boolean doCheck(Input input) {
        if (val.validate(input)) {
             return false;
        }

        List<Stuff> stuffs = da.loadStuffs(input);
        if (stuffs.isEmpty()) {
             return false;
        }

        BusinessStuff businessStuff = tr.transform(stuffs);
        if (null == businessStuff) {
            return false;
        }

       return calc.check(businessStuff);
    }
}
Run Code Online (Sandbox Code Playgroud)

我们需要进行大量的单元测试(例如,如果验证失败,或者DB中没有数据,......),这是不可能的.

我们的主要问题以及我们不能同意的是集成测试应涵盖多少:-)

我方面的目标是减少集成测试(测试金字塔).我从这里得到的只是一条快乐 - 不快乐的道路,执行从最后一行返回,只是为了看看我把这些东西放在一起它不会爆炸.

问题是,为什么测试结果是错误的并不容易,这让一些人感到不安(例如,如果我们只检查返回值,则隐藏测试为绿色因为某人更改了验证并返回false).当然,是的,我们可以涵盖所有案件,但这将是一个沉重的矫枉过正的imho.

对于这类问题,有没有人有一个很好的经验法则?还是推荐?读?谈论?博客帖子?关于这个主题的一切?

非常感谢提前!

PS:讽刺这个丑陋的例子,但很难将特定的代码部分翻译成一个例子.是的,人们可以争论抛出异常/使用不同的返回类型/等.但是由于外部依赖性,我们的手或多或少受到约束.

Sta*_*sev 5

如果遵循以下规则,很容易弄清楚测试应该驻留在哪里:

  • 我们检查Unit Tests级别的逻辑,然后检查是否在Component或System级别调用逻辑.
  • 我们不使用模拟框架(mockito,jmock等).

让我们一起来,但首先让我们就术语达成一致:

  • 单元测试 - 单独检查方法,类或其中一些
  • 组件测试 - 初始化应用程序的一部分,但不将其部署到App Server.示例可以是 - 在测试中初始化Spring上下文.
  • 系统测试 - 需要在App Server上进行完全部署.示例可以是:将HTTP REST请求发送到远程服务器.

如果我们建立一个平衡的金字塔,我们最终将对单元和组件级别进行大多数测试,其中很少将留给系统测试.这很好,因为较低级别的测试更快更容易.要做到这一点:

  • 我们应该尽可能地降低业务逻辑(最好是在域模型中),这样我们就可以轻松地单独测试它.每次你经历一组对象并在那里放置条件 - 理想情况下应该去域模型.
  • 但逻辑工作的事实并不意味着它被正确调用.这就是你需要组件测试的地方.初始化您的控制器以及服务和DAO,然后调用它一次或两次以查看是否调用了逻辑.

示例:用户名不能超过50个符号,只能有拉丁语以及一些特殊符号.

  • 单元测试 - 使用正确和错误的用户名创建用户,检查是否抛出异常,反之亦然 - 有效名称正在通过
  • 组件测试 - 检查当您将无效用户传递给Controller时(如果您使用Spring MVC - 您可以使用MockMVC执行此操作)它会抛出错误.在这里,您只需要传递一个用户 - 所有规则现在都已经过检查,此处您只对知道是否调用这些规则感兴趣.
  • 系统测试 - 实际上您可能不需要它们用于此场景.

这是一个更精细的例子,说明如何实现平衡金字塔.