zoukankan      html  css  js  c++  java
  • The Hacker's Guide To Python 单元测试

    The Hacker's Guide To Python 单元测试

    基本方式

    python中提供了非常简单的单元测试方式,利用nose包中的nosetests命令可以实现简单的批量测试。

    安装nose

    sudo pip install nose
    

    编辑测试文件

    # test_true.py
    def test_true():
        assert True
    
    def test_false():
        assert False
    

    执行测试

    # 命令, nosetests命令会加载所有以test_开头的文件,并执行所有以test_开头的函数
    nosetests -v
    # 输出
    test_true.test_true ... ok
    test_true.test_false ... FAIL
    
    ======================================================================
    FAIL: test_true.test_false
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/site-packages/nose/case.py", line 197, in runTest
        self.test(*self.arg)
      File "/xxxx/workspace/py/test/test_true.py", line 5, in test_false
        assert False
    AssertionError
    
    ----------------------------------------------------------------------
    Ran 2 tests in 0.007s
    
    FAILED (failures=1
    

    unittest是python提供了单元测试的标准库。

    # 为了兼容python 2.6和2.7
    try:
        import unittest2 as unittest
    except ImportError:
        import unittest
    
    class TestKey(unittest.TestCase):
        def test_keyh(self):
            a = ['a']
            b = ['a', 'b']
            self.assertEqual(a, b)
    

    输出如下,

    test_keyh (test_true.TestKey) ... FAIL
    
    ======================================================================
    FAIL: test_keyh (test_true.TestKey)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "/home/y/workspace/py/test/test_true.py", line 8, in test_keyh
        self.assertEqual(a, b)
    AssertionError: Lists differ: ['a'] != ['a', 'b']
    
    Second list contains 1 additional elements.
    First extra element 1:
    b
    
    - ['a']
    + ['a', 'b']
    
    ----------------------------------------------------------------------
    Ran 1 test in 0.006s
    
    FAILED (failures=1)
    

    此外,unittest.skipIf可以通过判断条件来选择是否进行测试,

    class TestSkipped(unittest.TestCase):
        @unitttest.skip("Do not run this")
        def test_failt(self):
            self.fail("This should not be run")
    
        @unittest.skipIf(mylib is None, "mylib is not available")
        def test_mylib(self):
            self.assertEqual(1, 1)
    

    此外,自定义setUptearDown函数可以单元测试开始和结束时自动调用。

    fixtures

    fixtures模块可以用来临时改变当前的测试环境。

    import fixtures
    import os
    
    class TestEnviron(fixtures.TestWithFixtures):
        def test_environ(self):
            fixture = self.useFixture(
                    fixtures.EnvironmentVariable("FOOBAR", "42")) # 临时增加一个环境变量FOOBAR
            self.assertEqual(os.environ.get("FOOBAR"), "42")
    
        def test_environ_no_fixture(self):
            self.assertEqual(os.environ.get("FOOBAR"), None) # 上面增加的环境变量的操作对于其他函数无效
    

    mock

    mock模块可以用来进行模拟测试,其主要功能就是模拟一个函数,类或实例的行为。

    由于网络测试环境的特殊性,最常用的使用就是模拟网络请求,具体例子如下,

    # test_mock.py
    import requests
    import unittest
    import mock
    
    class WhereIsPythonError(Exception):
        pass
    
    def is_python():
        try:
            r = requests.get("http://python.org")
        except IOError:
            pass
        else:
            if r.status_code == 200:
                return 'is python' in r.content
        raise WhereIsPythonError('something happened')
    
    def get_fake_get(status_code, content):
        m = mock.Mock()
        m.status_code = status_code
        m.content = content
        def fake_get(url):
            return m
        return fake_get
    
    def raise_get(url):
        raise IOError("unable to fetch url %s" % url)
    
    class TestPython(unittest.TestCase):
        @mock.patch('requests.get', get_fake_get(
            200, 'is python, hello'
            ))
        def test_python_is(self):
            self.assertTrue(is_python())
    
        @mock.patch('requests.get', get_fake_get(
            200, 'is not python, hello'
            ))
        def test_python_is_not(self):
            self.assertFalse(is_python())
    

    输出如下,

    # 命令
    nosetests --tests=test_mock -v
    # 结果
    test_python_is (test_mock.TestPython) ... ok
    test_python_is_not (test_mock.TestPython) ... ok
    
    ----------------------------------------------------------------------
    Ran 2 tests in 0.001s
    
    OK
    
  • 相关阅读:
    【HDOJ】2774 Shuffle
    【POJ】2170 Lattice Animals
    【POJ】1084 Square Destroyer
    【POJ】3523 The Morning after Halloween
    【POJ】3134 Power Calculus
    【Latex】如何在Latex中插入伪代码 —— clrscode3e
    【HDOJ】4801 Pocket Cube 的几种解法和优化
    【HDOJ】4080 Stammering Aliens
    【HDOJ】1800 Flying to the Mars
    SQL语法
  • 原文地址:https://www.cnblogs.com/coder2012/p/5092190.html
Copyright © 2011-2022 走看看