Skip to content

Instantly share code, notes, and snippets.

@gbozee
Created October 7, 2017 17:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save gbozee/d71200ca0beca09f3b547d2f22279448 to your computer and use it in GitHub Desktop.
Save gbozee/d71200ca0beca09f3b547d2f22279448 to your computer and use it in GitHub Desktop.
Testing Python programs with unittest
import unittest
class FizzBuzzException(Exception):
pass
def fizz_buzz(param):
result = ""
try:
variable = int(param)
except ValueError:
raise FizzBuzzException("This value is invalid")
if variable % 3 == 0:
result += "Fizz"
if variable % 5 == 0:
result += "Buzz"
return result
class FizzBuzzTestCase(unittest.TestCase):
def test_multiples_of_three_return_Fizz(self):
result = fizz_buzz(3)
self.assertEqual("Fizz", result)
def test_multiples_of_five_returns_Buzz(self):
result = fizz_buzz(5)
self.assertEqual("Buzz", result)
def test_multiples_of_fifteen_returns_FizzBuzz(self):
result = fizz_buzz(15)
self.assertEqual("FizzBuzz", result)
def test_when_strings_are_passed(self):
result = fizz_buzz("3")
self.assertEqual(result, "Fizz")
result = fizz_buzz("15")
self.assertEqual(result, "FizzBuzz")
with self.assertRaises(FizzBuzzException) as context:
result = fizz_buzz("nonsense")
self.assertEqual("This value is invalid", str(context.exception))
# if __name__ == '__main__':
# unittest.
import requests
import unittest
from unittest import mock
class Rexception(Exception):
pass
def make_call():
response = requests.get('https://api.github.com/users')
# import pdb
# pdb.set_trace()
if response.status_code < 400:
result = response.json()
if len(result) > 0:
return result[0]
return None
else:
raise Rexception(response.json()['error'])
return None
class MockClass(object):
def __init__(self, result, status_code):
self.status_code = status_code
self.result = result
def json(self):
return self.result
class RequestTestCase(unittest.TestCase):
def setUp(self):
self.patcher = mock.patch('requests.get')
self.mock_get = self.patcher.start()
def tearDown(self):
self.patcher.stop()
def test_api_call(self):
self.mock_get.return_value = MockClass([
{
"login": "pjhyett",
"id": 3,
"avatar_url": "https://avatars0.githubusercontent.com/u/3?v=4",
"gravatar_id": "",
},
{
"login": "biola",
"id": 4,
"avatar_url": "https://avatars2.githubusercontent.com/u/3?v=4",
"gravatar_id": "hello",
}
], status_code=200)
response = make_call()
self.assertEqual(response, {
"login": "pjhyett",
"id": 3,
"avatar_url": "https://avatars0.githubusercontent.com/u/3?v=4",
"gravatar_id": "",
})
self.mock_get.assert_called_once_with('https://api.github.com/users')
def test_api_call_2(self):
self.mock_get.return_value = MockClass([
], status_code=200)
response = make_call()
self.assertEqual(response, None)
self.mock_get.assert_called_once_with('https://api.github.com/users')
def test_api_call_failed(self):
self.mock_get.return_value = MockClass(
{'error': "Connection error"}, status_code=400)
with self.assertRaises(Rexception) as context:
response = make_call()
self.assertEqual("Connection error", str(context.exception))
self.mock_get.assert_called_once_with('https://api.github.com/users')
@gbozee
Copy link
Author

gbozee commented Oct 7, 2017

If I wanted to use the default test runner to run the above tests, I need to ensure the names of each files begin with a test_*.py. So the fizzbuzz.py becomes test_fizzbuzz.py and the github_api.py becomes test_github_api.py

The command to run the tests (Assuming python 3) is
python -m unittest discover

If we want to use other test runners supported by python nose and pytest
For nose

$ pip install nose
$ nosetest 

For pytest

$ pip install pytest
$ py.test

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