Last active
December 23, 2015 05:29
-
-
Save jacebrowning/6587691 to your computer and use it in GitHub Desktop.
'Mixing Unit Tests and Integration Tests' presentation from GRPUG. View at: http://nbviewer.ipython.org/6587691
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"name": "" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Mixing Unit Tests (mock) with Integration Tests (no mock)\n", | |
"\n", | |
"@JaceBrowning" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Basically:\n", | |
"\n", | |
" - use unittest skip decorates to read environment variables\n", | |
" - set environment variables in Makefiles" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## A function to test" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"def times_2_plus_1(arg1):\n", | |
" result = _expensive_x2(arg1) + 1\n", | |
" return result" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 40 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import time\n", | |
"\n", | |
"def _expensive_x2(arg1):\n", | |
" time.sleep(3) # expensive math, IO, 3rd-party API, etc.\n", | |
" return arg1 * 2" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 41 | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"times_2_plus_1(7)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 42, | |
"text": [ | |
"15" | |
] | |
} | |
], | |
"prompt_number": 42 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Without mock (an integration test)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import unittest\n", | |
"\n", | |
"\n", | |
"class TestMath(unittest.TestCase):\n", | |
" \n", | |
" def test_math(self):\n", | |
" self.assertEquals(15, times_2_plus_1(7))\n", | |
" \n", | |
" \n", | |
"suite = unittest.TestLoader().loadTestsFromTestCase(TestMath)\n", | |
"unittest.TextTestRunner(verbosity=2).run(suite)\n", | |
" \n", | |
"\n" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 43, | |
"text": [ | |
"<unittest.runner.TextTestResult run=1 errors=0 failures=0>" | |
] | |
} | |
], | |
"prompt_number": 43 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## With mock (a unit test)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import unittest\n", | |
"import mock\n", | |
"\n", | |
"\n", | |
"class TestMath2(unittest.TestCase):\n", | |
" \n", | |
" @mock.patch('__main__._expensive_x2', mock.Mock(return_value=14))\n", | |
" def test_math(self):\n", | |
" self.assertEquals(15, times_2_plus_1(7))\n", | |
" \n", | |
" \n", | |
"suite = unittest.TestLoader().loadTestsFromTestCase(TestMath2)\n", | |
"unittest.TextTestRunner(verbosity=2).run(suite)" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"metadata": {}, | |
"output_type": "pyout", | |
"prompt_number": 45, | |
"text": [ | |
"<unittest.runner.TextTestResult run=1 errors=0 failures=0>" | |
] | |
} | |
], | |
"prompt_number": 45 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Combination of unit test and integration test" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import unittest\n", | |
"import mock\n", | |
"import os\n", | |
"\n", | |
"ENV = 'TEST_INTEGRATION'\n", | |
"REASON = \"'{0}' not set\".format(ENV)\n", | |
"\n", | |
"\n", | |
"class TestMath3(unittest.TestCase):\n", | |
" \n", | |
" @mock.patch('__main__._expensive_x2', mock.Mock(return_value=14))\n", | |
" def test_math(self):\n", | |
" self.assertEquals(15, times_2_plus_1(7))\n", | |
" \n", | |
" @unittest.skipUnless(os.getenv(ENV), REASON)\n", | |
" def test_math_integration(self):\n", | |
" self.assertEquals(15, times_2_plus_1(7))\n", | |
" \n", | |
" \n", | |
"suite = unittest.TestLoader().loadTestsFromTestCase(TestMath3)\n", | |
"results = unittest.TextTestRunner(verbosity=2).run(suite)\n", | |
"print results\n", | |
"print results.skipped" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"<unittest.runner.TextTestResult run=2 errors=0 failures=0>\n", | |
"[]\n" | |
] | |
} | |
], | |
"prompt_number": 55 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Disabling the integration tests..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import os\n", | |
"os.environ['TEST_INTEGRATION'] = ''" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 49 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Enabling the integration tests..." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import os\n", | |
"os.environ['TEST_INTEGRATION'] = '1'" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 54 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Practical usage\n", | |
"\n", | |
"\n", | |
" package/\n", | |
" __init__.py\n", | |
" module1.py\n", | |
" module2.py\n", | |
" test/\n", | |
" __init__.py # integration tests for the package\n", | |
" test_module1.py # unit and integration tests for the module\n", | |
" test_module2.py # unit and integraiton tests for the module\n", | |
"\n", | |
"\n", | |
"\n", | |
"Makefile:\n", | |
"\n", | |
" ...\n", | |
" \n", | |
" .PHONY test\n", | |
" test:\n", | |
" nosetests\n", | |
"\n", | |
" .PHONY tests\n", | |
" tests:\n", | |
" TEST_INTEGRATION=1 nosetests --verbose\n", | |
" \n", | |
" ...\n" | |
] | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment