django测试的HTML报告

django测试的HTML报告,django,testing,Django,Testing,我有一个Django项目,其中包含一个API(使用rest框架创建,如果这在任何地方都有效的话)。我已经为API添加了一些测试,但是为了全面了解测试,无论是通过测试、失败测试还是丢失测试,我需要创建一个HTML报告。 测试完成后,应生成一个HTML表格报告,其中显示测试期间覆盖的端点和HTTP响应、测试结果以及缺少测试的组合 不幸的是,我不明白我该怎么做。我知道覆盖率可以为我提供详细的html报告,但这不是我需要的,我需要这样的东西: |端点描述| 200 | 400 | 403 | 404 |

我有一个Django项目,其中包含一个API(使用rest框架创建,如果这在任何地方都有效的话)。我已经为API添加了一些测试,但是为了全面了解测试,无论是通过测试、失败测试还是丢失测试,我需要创建一个HTML报告。 测试完成后,应生成一个HTML表格报告,其中显示测试期间覆盖的端点和HTTP响应、测试结果以及缺少测试的组合

不幸的是,我不明白我该怎么做。我知道覆盖率可以为我提供详细的html报告,但这不是我需要的,我需要这样的东西:

|端点描述| 200 | 400 | 403 | 404 |
|GET/endpoint1 | PASS | PASS | PASS | N/A |
|后/终点1 |通过|失败|缺失|不适用|

有人知道吗?也许一些LIB可以帮助解决这个问题,或者我应该使用什么策略


提前感谢您

由于Django使用python的标准
unittest
库,您必须调整它的一些部分

首先,您需要某种方法来指定哪些测试实际测试哪个端点。定制装饰器非常方便:

from functools import wraps

def endpoint(path, code):
    """
    Mark some test as one which tests specific endpoint.
    """
    def inner(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            return func(*args, **kwargs)
        return wrapper

    inner._endpoint_path = path
    inner._endpoint_code = code
    return inner


class MyTestCase(TestCase):
    @endpoint(path='/path/one', code=200)
    def test_my_path_is_ok(self):
        response = self.client.get('/path/one?foo=bar')
        self.assertEqual(response.status_code, 200)

    @endpoint(path='/path/one', code=404)
    def test_my_path_expected_errors(self):
        response = self.client.get('/path/one?foo=qux')
        self.assertEqual(response.status_code, 404)

    def test_some_other_stuff(self):
        # this one will not be included in our results grid.
        pass
您可以使用“神奇”的方法(例如,特殊方法的名称来猜测他们正在测试的端点),但是,对吗

然后,您需要一种方法来收集测试结果,特别是测试端点的结果。在这里,我们创建了一个
unittest.TestResult
的(非常草稿)子类来处理它:

class EndpointsTestResult(TestResult):
    def __init__(self):
         super(EndpointsTestResult, self).__init__()
         self.endpoint_results = {}

    def addError(self, test, err):
        super(EndpointsTestResult, self).addError(test, err)
        if hasattr(test, '_endpoint_path'):
            branch = self.endpoint_results.setdefault(getattr(test, '_endpoint_path'), {})
            branch[getattr(test, '_endpoint_code')] = 'MISSING'

    def addFailure(self, test, err):
        # similar as addError()

    def addSuccess(self, test):
        # similar as addError()
最后是时候实际输出我们的结果了。让我们创建一个子类
unittest.TextTestRunner
,并在自定义运行程序中指定它:

class EndpointsTestRunner(TextTestRunner):
    def _makeResult(self):
         self._result = EndpointsTestResult()
         return self._result

    def run(self, test):        
        super(EndpointsTestRunner).run(test)
        # After running a test, print out the table
        generate_a_nifty_table(self._result.endpoint_results)


class EndpointsDjangoRunner(django.test.runner.DiscoverRunner):
    test_runner = EndpointsTestRunner
现在我们有了自定义的
端点dJangorRunner
,我们应该在
设置.py
中指定它:

TEST_RUNNER = 'path.to.the.EndpointsDjangoRunner'

就这样。如果您发现代码中有任何令人尴尬的错误,请告诉我。

迟到了,但这是我为Django测试输出HTML测试报告的解决方案。(基于)

如果将以下类放置在tests/html_test_reporter.py中,则可以将其用作DiscoveryRunner,该DiscoveryRunner经过修补以使用HTMLTestRunner

from django.test.runner import DiscoverRunner
from HtmlTestRunner import HTMLTestRunner

class MyHTMLTestRunner(HTMLTestRunner):
    def __init__(self, **kwargs):
        # Pass any required options to HTMLTestRunner 
        super().__init__(combine_reports=True, report_name='all_tests', add_timestamp=False, **kwargs)

class HtmlTestReporter(DiscoverRunner):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # Patch over the test_runner in the super class.
        html_test_runner = MyHTMLTestRunner
        self.test_runner=html_test_runner
然后,使用以下命令运行此操作:

python manage.py test -v 2 --testrunner tests.html_test_reporter.HtmlTestReporter
默认情况下,Django项目使用Django.test.runner.DiscoverRunner搜索测试,然后使用PyTest运行测试。HTMLTestRunner可以与PyTest一起使用以输出HTML测试报告,但似乎可以通过DiscoveryRunner将PyTest配置为使用HTMLRunner


希望这有帮助

您的测试是一堆
TestCase
子用例,您通过执行
/manage.py test
来运行它们,对吗?是的,这正是我的意思,根据您的答案,在一段时间内开始实现!我一定会让你知道事情的进展!非常感谢!当使用decorator并尝试测试实现时,我会遇到一个
TypeError:endpoint()正好接受3个参数(给定2个)
错误。第一个参数func one不应该是它修饰的函数?也许
func
arg应该是internal的方法arg,而不是修饰器的方法args@koslib,请尝试(稍微)更新的版本。有帮助吗?不幸的是,现在我无法检查和测试我的代码,我将稍后再尝试。Alex,这似乎有效。现在,我正在将它与项目所需的现有django nose测试套件集成。