美文网首页
Django单元测试

Django单元测试

作者: null_fca6 | 来源:发表于2018-10-15 18:46 被阅读0次

为什么需要自动化测试

  • 对于大项目,对每个单元进行测试可以快速定位错误,确保项目质 量
  • 在 python 中,利用 python 的测试化模块搭建一些测试不会比手 动测试一些数据更麻烦
    • 多写一些代码
    • (几乎)不和终端的输入输出打交道
    • 少和单步调试打交道
  • 在 python 交互式终端的输入输出,可以马上成为一些测试样例
  • 带有和 Java 类似的单元测试框架,可以提取出不同测试用例的相 同步骤
  • 回归测试:一个测试用例可以在开发过程中反复测试,保证加入新 功能后不会妨碍原有功能的运转

测试覆盖率

  • 定义:在运行测试时运行的代码占总代码量的比例
  • 作用:找出没有被测试过的函数和代码行
  • 自带 trace.py:python -m trace --help
    • --count 统计每行被执行的次数
    • --trace 程序每执行一行,就将这一行打印到标准输出
    • 统计被执行的函数名、调用关系、累积多次运行的总次数、标出没有被运行的代码行⋯⋯

Doctest

  • python 的 docstring 中有很多在交互式终端中运行的例子
  • doctest 可以检查 docstring 中样例的正确性
  • 同样的,可以把手动测试的终端输出放进 docstring 里,变成一个 测试用例
  • 注意:一般小型的或者简单的功能可以使用,但是较大的项目或者较复杂的功能并不推荐使用doctest

下面是一个样例

def factorial(n): 
"""Return the factorial of n, an exact integer >= 0.

>>> [factorial(n) for n in range(6)] 
[1, 1, 2, 6, 24, 120] 
>>> factorial(30) 265252859812191058636308480000000 
>>> factorial(-1) 
Traceback (most recent call last): 
    ...
 ValueError: n must be >= 0 
"""

import math 
if not n >= 0: 
    raise ValueError("n must be >= 0") 
result = 1 
factor = 2 
while factor <= n: 
    result *= factor 
    factor += 1 
return result
if __name__ == "__main__": 
    import doctest 
    doctest.testmod()

Unittest

  • 基于 JUnit 测试框架 (JAVA)
  • 比 doctest 更加灵活, 功能更加强大
  • 我们要提到的django单元测试就是基于unittest的,下面先简要介绍下如何使用unittest

如何使用Unittest

  • 先构造 unittest.TestCase 的子类
  • unittest.main() 用法
    • unittest.main() 函数将会实例化所有当前 py 文件下的 TestCase 的 子类并且执行以’test’ 开头的函数
    • 若需要跨文件测试,则只需 import 含 testBase 子类的 py 文件再调 用 unittest.main() 即可
  • startUp 与 tearDown 函数
    • startUp 将会在每个 test 函数执行前被调用
    • tearDown 将会在每个 test 函数执行后被调用
    • 通常用来初始化以及清除测试过程中的一些代码
  • 常用的TestCase函数:
    • assert_(expr[, msg]) 与 failUnless(expr[, msg])
      • 会对不正确的结果报错
    • assertEqual(x, y[, msg]) 与 failUnlessEqual(x, y[, msg])
      • 值不等时报错并输出二者的值
    • assertAlmostEqual(x, y[, places[, msg]]) 与 failUnlessAlmostEqual(x, y[, places[, msg]])
      • 值不近似等时报错,用于浮点数的判等
    • assertRaises(exc, callable, ...) 与 failUnlessRaises(exc, callable, ...)
      • 该回调函数没有抛出 exc 的异常则报错

下面是一个样例

class ProductTestCase(unittest.TestCase): 
    def testIntegers(self): 
        x = 3 
        y = 4 
        p = my_math.product(x, y) 
        self.failUnless(p == x*y, 'Integer␣multiplication␣failed') 
if __name__ == '__main__': unittest.main()
*************************Wrong************************* 
F 
======================================================== 
FAIL: testIntegers (__main__.ProductTestCase) 
-------------------------------------------------------
Traceback (most recent call last): 
                File "test_my_math.py", line 17, in testIntegers self.failUnless(p == x*y, 'Integer␣multiplication␣ failed') 
AssertionError: Integer multiplication failed 
-------------------------------------------------------
Ran 1 tests in 0.001s 
FAILED (failures=1)

*************************Correct************************* 
. 
-------------------------------------------------------
Ran 1 tests in 0.001s 
OK
  • 当测试结果正确时,返回一个.而不正确时是返回一个F

源码检查

  • PyChecker
    • 检查 python 源码错误,例如传参错误,没有导入模块,同一作用域 中重定义函数、类方法等。
    • 使用:pychecker [options] file1.py file2.py ...
  • PyLint
    • 支持大部分 PyChecker 功能
    • 更强大的功能,例如检查变量名是否符合规定,检查一行代码的长 度,一个声明过的接口是否被实现
    • 使用:pylint [options] module_or_package
  • 结合 unittest 使用
    • 代码中嵌入
    • PyChecker 与 PyLint 集成到 IDE

Django单元测试

讲了这么多python的单元测试,那如何进行Django的单元测试呢?

  • 在Django的单元测试中,仍然推荐使用python的unittest模块,像我们刚刚在上面提到的使用方法,使用类名为django.test.TestCase,继承于python的unittest.TestCase。
class TestDefault(TestCase):

    def setUp(self):
        # 设置配置
        settings.IGNORE_WECHAT_SIGNATURE = True

        # user1 => not bind
        # user2 => bind
        User.objects.create(open_id='abc')
        User.objects.create(open_id='a', student_id='2016013265')

        # textMsgs => 用户一般可能输入(成功)
        self.textMsgs = ['balabala', 'gg', '抢火车票']

    # 是否返回帮助
    def is_default(self, content):
        pattern = '对不起,没有找到您需要的信息:('
        return content.find(pattern) != -1

    def test_text(self):
        users = User.objects.all()

        for user in users:
            for textMsg in self.textMsgs:
                fromUser = user.open_id
                curTime = str(getTimeStamp(datetime.datetime.now()))
                msgId = str(random.randint(0, 99999)) + curTime
                data = getTextXml(fromUser, curTime, textMsg, msgId)

                response = self.client.post(
                    path='/wechat/',
                    content_type='application/xml',
                    data=data
                )

                content = str(response.content.decode('utf-8'))
                self.assertEqual(self.is_default(content), True)

  • 执行目录下所有的测试(所有的test*.py文件):

python manage.py test

运行测试的时候,测试程序会在所有以test开头的文件中查找所有的test cases(inittest.TestCase的子类),自动建立测试集然后运行测试。(注意是所有app的test文件,包括子目录中的)

  • 执行项目的所有的test测试:

python manage.py test

运行结果:


image.png
  • 执行项目某个下tests包里的测试:

python manage.py xxx.tests

  • 单独执行某个test case:

python manage.py xxx.TestDefault

  • 单独执行某个测试方法:

python manage.py xxx.TestDefault.testxxx/py

  • 通配测试文件名:

python manage.py test–pattern=”tests_*.py”

  • 启用warnings提醒:

python -Wall manage.py test

数据库

测试是需要数据库的,django会为测试单独生成数据库。不管你的测试是否通过,当你所有的测试都执行过后,这个测试数据库就会被销毁。

  • 默认情况下,测试数据库的名字是test_DATABASE_NAME,DATABASE_NAME是你在settings.py里配置的数据库名;
    如果你需要给测试数据库一个其他的名字,在settings.py中指定TEST_DATABASE_NAME的值
  • 使用sqlite3时,数据库是在内存中创建的。
    除了数据库是单独创建的以外,测试工具会使用相同的数据库配置--DATABASE_ENGINE, DATABASE_USER, DATABASE_HOST等等.
    创建测试数据库的用户DATABASE_USER(settings中)指定,所以你需要确认 DATABASE_USER有足够的权限去创建数据库。

为了保证所有的测试都从干净的数据库开始,执行顺序如下:

  • 1.所有的TestCase子类首先运行。
  • 2.所有其他的单元测试(unittest.TestCase,SimpleTestCase,TransactionTestCase)。
  • 3.其它的测试(例如doctests等)

加速测试

  • 可以将PASSWORD_HASHERS设置为更快的算法:
PASSWORD_HASHERS = (
    'django.contrib.auth.hashers.MD5PasswordHasher',
)

travis CI与django的单元测试

  • 在.travis.yml文件中加入(修改):
script: 
    - python manage.py test

参考

相关文章

  • 技术博客汇总

    对微信公众号接口的单元测试 Github与Travis CI测试与部署 Django单元测试 NodeJs单元测试...

  • Django单元测试指定配置文件(PyCharm设置)

    创建指定配置文件编写单元测试 创建单元测试Django tests 编辑Configurationimage.pn...

  • Django - 单元测试

    Django - 单元测试 Unit tests VS doctest Unit tests —— unittes...

  • django单元测试总结

    一、django单元测试框架: 编写测试用例: 引用TestCase基类:django.test继承了python...

  • Django 单元测试

    Django自带单元测试的模块django.test,该模块使用了Python的标准库unitest,基于类的方法...

  • Django单元测试基础知识

    相关资源 Django官方文档unittest文档 简单的例子 关于django的单元测试,需要知道的是 对于每一...

  • Django fixtures

    Fixtures在Django测试中的使用 在对Django项目做单元测试时,经常需要生成或者导入一些初始数据。对...

  • Django单元测试

    本文主要介绍基于Django框架开发的web程序进行单元测试。 因为使用django程序的view函数的参数一般为...

  • django单元测试

    在项目开发过程中,单元测试必不可少,通过测试可以减少bug数,提升代码质量。 Django支持单元测试,在添加应用...

  • Django单元测试

    为什么需要自动化测试 对于大项目,对每个单元进行测试可以快速定位错误,确保项目质 量 在 python 中,利用 ...

网友评论

      本文标题:Django单元测试

      本文链接:https://www.haomeiwen.com/subject/mwwfzftx.html