检测不正确的断言方法

ale*_*cxe 15 python testing unit-testing static-code-analysis python-unittest

在最近的一次代码审查中,我偶然发现了一个不容易发现的问题 - assertTrue()使用而不是assertEqual()基本上导致了一个没有测试的测试.这是一个简化的例子:

from unittest import TestCase


class MyTestCase(TestCase):
    def test_two_things_equal(self):
        self.assertTrue("a", "b")
Run Code Online (Sandbox Code Playgroud)

这里的问题是测试会通过; 从技术上讲,代码是有效的,因为assertTrue有这个可选msg参数("b"在这种情况下获取值).

我们能不能依靠审核代码的人来发现这类问题?是否有办法来自动检测使用静态代码分析它flake8还是pylint

Gho*_*per 10

Python现在有一个类型提示系统,可以进行静态代码分析.使用此系统,您可以要求函数的第一个参数assertTrue始终是boolean.问题是assertTrue你没有定义,而是由unittest包定义.不幸的是,unittest包没有添加类型提示.虽然有一个相当简单的方法:只需定义自己的包装器.

from unittest import TestCase

class TestCaseWrapper(TestCase):
    def assertTrue(self, expr: bool, msg=None): #The ": bool" requires that the expr parameter is boolean.
        TestCase.assertTrue(self, expr, msg)

class MyTestCase(TestCaseWrapper):
    def test_two_things_equal(self):
        self.assertTrue("a", "b") #Would give a warning about the type of "a".
Run Code Online (Sandbox Code Playgroud)

然后,您可以像这样运行类型检查器:

python -m mypy my_test_case.py
Run Code Online (Sandbox Code Playgroud)

这应该会给你一个关于"a"是一个字符串而不是一个布尔值的警告.关于这一点的好处是它可以在自动化测试框架中自动运行.此外,PyCharm将检查您的代码中的类型,如果您提供它们并突出显示任何错误.

  • 在制作这样的包装器时,使用`functools.wraps`制作文档并从原始函数继承它也很有用. (3认同)

Leo*_*eon 5

几年前,我想出了一种通用的方法/方法来确保测试的质量.测试规范可以简化为两个条款:

  1. 它必须通过才能正确实现正在测试的功能,并且
  2. 对于正在测试的功能的不正确/损坏实现,它必须失败

据我所知,虽然要求1经常被执行,但很少注意要求2.

通常

  • 测试套件已创建,
  • 代码是针对它运行的,
  • 任何失败(由于代码或测试中的错误)都是固定的
  • 当我们相信我们的代码和测试是好的时,我们就会遇到这种情况.

实际情况可能是(某些)测试包含(会)阻止它们捕获代码中的错误的错误.因此,看到测试通过不应该对关心系统质量的人表现出很大的安宁,直到他们确信测试确实能够检测出他们设计的问题1.一个简单的方法是实际引入这些问题,并检查它们是否不会被测试忽视!

在TDD(测试驱动开发)中,这个想法只是部分遵循 - 建议在代码之前添加测试,看它失败(它应该,因为还没有代码),然后通过编写代码来修复它.但是由于缺少代码而导致测试失败并不意味着在代码错误的情况下它也会失败(这似乎适用于您的情况)!

因此,测试套件的质量可以测量为它能够检测到的错误的百分比.任何逃避测试套件的合理的2个错误都表明了一个覆盖该场景的新测试用例(或者,如果测试套件应该捕获该错误,则会发现测试套件中的错误).这也意味着套件的每个测试必须能够捕获至少一个错误(否则,该测试完全没有意义).

我正在考虑实现一个有助于采用这种方法的软件系统(即允许在代码库中注入和维护人为错误并检查测试如何响应它们).这个问题充当了触发器,我将立即开始研究它.希望在一周内把东西放在一起.敬请关注!

编辑

该工具的原型版现已在https://bitbucket.org/leon_manukyan/trit上提供.我建议克隆存储库并运行演示流程.


1对于更广泛的系统/情况(通常都与安全性/安全性有关),此声明的更通用版本是正确的:

针对某些事件设计的系统必须针对此类事件进行常规测试,否则易于降级以完全无法对感兴趣的事件做出反应.

举个例子 - 你家里有火灾报警系统吗?你什么时候见证它上次工作?如果在火灾期间保持沉默怎么办?现在去房间里抽烟吧!

2在这种方法的范围,像臭虫后门(例如,当行为不端功能只有在URL中传递等于https://www.formatmyharddrive.com/?confirm=yesofcourse)不是一个合理