Django:如何在单元测试中隐藏 Traceback 以提高可读性?

标签 django unit-testing

我发现为一个简单的失败的单元测试获取如此多的细节有点烦人。除了实际定义的断言消息之外,是否可以抑制所有内容?

Creating test database for alias 'default'...
.F
======================================================================
FAIL: test_get_sales_item_for_company (my_app.tests.SalesItemModelTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/kave/projects/my/my_app/tests.py", line 61, in test_get_sales_item_for_company
    self.assertEqual(sales_items.count(), 1, 'Expected one sales item for this company, but got %s' % sales_items.count())
AssertionError: Expected one sales item for this company, but got 2

----------------------------------------------------------------------
Ran 2 tests in 0.313s

FAILED (failures=1)
Destroying test database for alias 'default'...

我觉得这有点不必要。我需要知道失败的测试名称(方法)和断言消息。真的不需要回溯..
Traceback (most recent call last):
  File "/home/kave/projects/my/my_app/tests.py", line 61, in test_get_sales_item_for_company
    self.assertEqual(sales_items.count(), 1, 'Expected one sales item for this company, but got %s' % sales_items.count())

最佳答案

猴子修补救援。您可以通过子类化 Django 的 TestCase 来摆脱失败的回溯,而无需触及 Django 安装,如下所示:

import types
from django.utils.unittest.result import failfast
from django.test import TestCase

@failfast
def addFailureSansTraceback(self, test, err):
    err_sans_tb = (err[0], err[1], None)
    self.failures.append((test, self._exc_info_to_string(err_sans_tb, test)))
    self._mirrorOutput = True

class NoTraceTestCase(TestCase):
    def run(self, result=None):
        result.addFailure = types.MethodType(addFailureSansTraceback, result)
        super(NoTraceTestCase, self).run(result)

现在只需将您的测试用例作为 NoTraceTestCase 的子类而不是 TestCase你很高兴。没有更多的失败追溯。 (请注意,异常仍会打印回溯。如果您愿意,您可以类似地修补这些。)

以下是它的工作原理(感谢 Jason Pratt for the quick lesson on monkey patching ):
  • Django 的测试运行器调用 TestCase 的 run每次测试运行的方法。 result参数是 django.utils.unittest.result.TestResult 的一个实例类,它处理向用户显示测试结果。每当测试失败时,run调用以下电话:result.addFailure(self, sys.exc_info()) .这就是回溯的来源——作为 sys.exc_info() 返回的元组中的第三项.
  • 现在,只需覆盖 run使用原始代码的副本并根据需要对其进行调整将起作用。但是 run方法是一个很好的 75 行长,所有需要更改的只是那一行,无论如何,为什么要错过猴子修补的乐趣呢?
  • result.addFailure分配更改 addFailure result 中的方法传递给 NoTraceTestCase 的 run 的对象新定义的 addFailureSansTraceback 方法函数——首先转换为 result - 与 types.MethodType 的对象兼容方法.
  • super call 调用 Django 现有的 TestCase run .现在,当现有代码运行时,调用 addFailure实际上会调用新版本,即 addFailureSansTraceback .
  • addFailureSansTraceback addFailure 的原始版本做了什么确实 -- 复制了两行代码 -- 除了添加一行用 None 替换回溯(对 err_sans_tb 的赋值,用于代替下一行中的 err)。就是这样。
  • 注意原文addFailure有一个 failfast装饰器,以便导入和使用。老实说,我没有看过它的作用!

  • 免责声明:我没有彻底研究过 Django 的测试代码。这只是让它在常见情况下工作的快速补丁。使用风险自负!

    关于Django:如何在单元测试中隐藏 Traceback 以提高可读性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11908784/

    相关文章:

    unit-testing - 用于 http 处理程序测试的 Golang 模拟函数

    unit-testing - Pester:并非所有模拟函数都被拦截

    python - 在 python 中编写类似单元测试的 DRY 方法

    python - django 按不同字段的最新日期对查询集进行排序

    django - Celery:从任务中撤销整个链的干净方式

    Python 2.6 : proper usage of unittest. 测试套件

    c# - 如何在 Visual Studio 2010 中执行单元测试之前不构建

    django - django 的 MS Access 后端

    python - Django inlineformset_factory 和 ManyToMany 字段

    django - 关于 Django 的 CSRF 保护问题