Skip to content

Instantly share code, notes, and snippets.

@JeOam
Last active September 3, 2019 04:33
Show Gist options
  • Save JeOam/398014365afc06cbdea0 to your computer and use it in GitHub Desktop.
Save JeOam/398014365afc06cbdea0 to your computer and use it in GitHub Desktop.
Unit Test Notes

unittest — Unit testing framework

The Python unit testing framework, sometimes referred to as “PyUnit”.

unittest supports test automation, sharing of setup and shutdown code for tests, aggregation of tests into collections, and independence of the tests from the reporting framework. The unittest module provides classes that make it easy to support these qualities for a set of tests.

To achieve this, unittest supports some important concepts:

  • test fixture
    • A test fixture represents the preparation needed to perform one or more tests, and any associate cleanup actions. This may involve, for example, creating temporary or proxy databases, directories, or starting a server process.
  • test case
    • A test case is the smallest unit of testing. It checks for a specific response to a particular set of inputs. unittest provides a base class, TestCase, which may be used to create new test cases.
  • test suite
    • A test suite is a collection of test cases, test suites, or both. It is used to aggregate tests that should be executed together.
  • test runner
    • A test runner is a component which orchestrates the execution of tests and provides the outcome to the user. The runner may use a graphical interface, a textual interface, or return a special value to indicate the results of executing the tests.

The standard workflow is:

  1. You define your own class derived from unittest.TestCase.
  2. Then you fill it with functions that start with test_.
  3. You run the tests by placing unittest.main() in your file, usually at the bottom.

Example: test_unittest.py

import unittest
class TestUM(unittest.TestCase):
    def setUp(self):
        pass

    def test_example(self):
        self.assertEqual(true, true)

if __name__ == '__main__':
    unittest.main()

Running unittests:

$ python test_unittest.py

Ref:

@JeOam
Copy link
Author

JeOam commented Jun 13, 2015

pytest is a mature full-featured Python testing tool that helps you write better programs.

The unit test style of deriving from unittest.TestCase is something unittest shares with it’s xUnit counterparts like JUnit. It’s informative to know that inheritance is quite important in some languages to get the test framework to work right.

But this is Python. We have very powerful introspection and runtime capabilities, and very little information hiding. Pytest takes advantage of this.

An identical test as above could look like this if we use pytest: test_pytest.py

def test_example():
    assert(true)

Running unittests:

$ py.test test_pytest.py

Test Discovery: pytest.ini

[pytest]
minversion = 2.6.4
python_files = 'test_*.py'

Ref:

@JeOam
Copy link
Author

JeOam commented Jun 16, 2015

pytest 运行时使用断点:
在需要设置断点的地方加上语句:pytest.set_trace()

pytest 中时,显示 print 运行产生的内容:py.test -s

@JeOam
Copy link
Author

JeOam commented Jul 13, 2015

WebSocket Test Case

from tornado import gen

import pytest
import tornadoredis
from tornado.testing import AsyncHTTPTestCase, gen_test
from tornado.httpclient import HTTPRequest
from tornado.websocket import websocket_connect
from tornado.web import Application, create_signed_value

class WebSocketBaseTestCase(AsyncHTTPTestCase):
    @gen.coroutine
    def ws_connect(self, path):
        url = 'ws://127.0.0.1:%d%s' % (self.get_http_port(), path)
        secure_cookies = create_signed_value(APP_SETTINGS['cookie_secret'],
                                             't', self.token)
        headers = {'Cookie': '='.join(('t', secure_cookies)),
                   'protocol': 'http',
                   'Content-Type': 'application/x-www-form-urlencoded',
                   }
        ws = yield websocket_connect(HTTPRequest(url, headers=headers))
        raise gen.Return(ws)

    def setUp(self):
        super(WebSocketBaseTestCase, self).setUp()
        self._client = tornadoredis.Client()
        self._client.connect()

    def tearDown(self):
        super(WebSocketBaseTestCase, self).tearDown()
        self._client.disconnect()

class WebSocketTest(WebSocketBaseTestCase):
    def get_app(self):
        _settings = {
            'cookie_secret': APP_SETTINGS['cookie_secret']
        }
        router = [
            ('/websocket', WebSocketHandler),
        ]
        init_kwargs = {
            'Session': self.session_cls
        }
        f = lambda n: (n[0], n[1], init_kwargs)
        handlers = map(f, router)
        return Application(handlers, **_settings)


    @gen_test
    def test_websocket_message(self):
        ws = yield self.ws_connect('/websocket')
        ws.write_message('ping')
        response = yield ws.read_message()
        self.assertEqual(response, 'pong')
        ws.close()

@JeOam
Copy link
Author

JeOam commented Jul 20, 2015

Coverage Report:

pip install pytest-cov
py.test --cov .

@JeOam
Copy link
Author

JeOam commented Oct 19, 2015

mock:

import mock
import unittest

from Project.package import object_a

class SomeTestCase(unittest.TestCase):
    # the same: @mock.patch.object(object_a, 'method_a')
    @mock.patch("Project.package.object_a.method_a")
    def test_some_test(self, mock_function_a):
       mock_function_a.return_value = "return_value"

monkeypatching:

from Project.package import object_a

def mock_method_a(name)
    return name

def test_some_test(monkeypatch):
    monkeypatch.setattr(object_a, 'method_a', mock_method_a)

monkeypatching in class, notice that this is only valid for "standard" pytest classes (not unittest.TestCase subclasses).:

class Test:
    def setup_calss(self):
        pass
    def teardown_class(self):
       pass
    def test_some_function(self, monkeypatch):
       pass

@JeOam
Copy link
Author

JeOam commented Nov 3, 2015

Mock python builtin functions in pytest:

import __builtin__
...
monkeypatch.setattr(__builtin__, 'raw_input', mock_raw_input)

@JeOam
Copy link
Author

JeOam commented Nov 18, 2015

Asserting that a certain exception is raised in pytest:

import pytest
with pytest.raises(Exception):
    f()

@bingoabs
Copy link

Thanks, learn so much, happy everyday for you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment