From 93039e1ac17bc26dd4a45ef6b5bec36dacee2612 Mon Sep 17 00:00:00 2001 From: warren_driscoll Date: Sun, 12 May 2024 14:44:26 -0400 Subject: [PATCH] Copy the samples from pytest, but use unittest --Probably due to changes in source libraries, the pytest mock example is not working. But, it could still be copied to creat default unittest example. --- python/unittest/README.md | 8 ++- python/unittest/app/some_service.py | 12 ++++ python/unittest/app/thing.py | 7 +++ python/unittest/tests/test_double.py | 69 +++++++++++++++++++++ python/unittest/tests/test_thing.py | 13 ++++ python/unittest/tests/test_thing_fixture.py | 14 +++++ python/unittest/todo_project_name_test.py | 7 --- 7 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 python/unittest/app/some_service.py create mode 100644 python/unittest/app/thing.py create mode 100644 python/unittest/tests/test_double.py create mode 100644 python/unittest/tests/test_thing.py create mode 100644 python/unittest/tests/test_thing_fixture.py delete mode 100644 python/unittest/todo_project_name_test.py diff --git a/python/unittest/README.md b/python/unittest/README.md index 413eec66..792c4cb6 100644 --- a/python/unittest/README.md +++ b/python/unittest/README.md @@ -2,12 +2,16 @@ #### Setup -Does not need any additional libraries, as unittest is part of the +Does not need any additional libraries, as unittest and unittest.mock are part of the standard Python library. #### Running the tests -To execute the tests run `python -m unittest todo_project_name_test` +To execute the tests run `python -m unittest` from this directory `py -m unittest` on windows. The methods starting with 'test_' are going to be discovered automatically. + +Adding to vscode: + +Navigate to beaker tab on the sidebar. Choose configure. Python tests may be supported out of the box on vs code. Choose unittest flavour. Choose test_* detection pattern. The test tab should now populate with all tests, and you can run and debug from the test tab. diff --git a/python/unittest/app/some_service.py b/python/unittest/app/some_service.py new file mode 100644 index 00000000..09732346 --- /dev/null +++ b/python/unittest/app/some_service.py @@ -0,0 +1,12 @@ +import time + + +class SomeService: + def service_call(self, number): + # going into db looong complex processing + time.sleep(3) + return f"{number}" + + +def interact_with_service(service, number): + return service.service_call(number) diff --git a/python/unittest/app/thing.py b/python/unittest/app/thing.py new file mode 100644 index 00000000..57ba2520 --- /dev/null +++ b/python/unittest/app/thing.py @@ -0,0 +1,7 @@ +class Thing: + + def __init__(self, name): + self.name = name + + def return_hello_name(self): + return "Hello " + self.name + "!" diff --git a/python/unittest/tests/test_double.py b/python/unittest/tests/test_double.py new file mode 100644 index 00000000..e237ffa7 --- /dev/null +++ b/python/unittest/tests/test_double.py @@ -0,0 +1,69 @@ +from app.some_service import interact_with_service, SomeService +import unittest +import unittest.mock as mock + +# TestDouble concep +# - https://martinfowler.com/bliki/TestDouble.html + + +# +# Example of using stubs +# 1. Hand written class - ServiceStub +# 2. using unittest.mock patch facilities +# + + +class ServiceStub: + @staticmethod + def service_call(number): + return "42" + +class TestDouble(unittest.TestCase): + + def test_stub(self): + result = interact_with_service(ServiceStub(), 0) + self.assertEqual(result, "42") + + def test_stub_2(self): + expected = 'foo' + + def method_stub(self, some_number): + return 'foo' + + mock.patch( + 'app.some_service.SomeService.service_call', + method_stub + ) + + actual = SomeService().service_call(expected) + self.assertEqual(expected, actual) + + # + # Example of using mock: + # + @mock.patch('app.some_service.SomeService.service_call') + def test_mock_service_call_class(self, service_call) -> None: + rpc = SomeService() + rpc.service_call(-135) + SomeService.service_call.assert_called_with(-135) + + + @mock.patch('app.some_service.SomeService.service_call') + def test_mock_service_call_function(self, service_call) -> None: + rpc = SomeService() + interact_with_service(rpc, 100500) + SomeService.service_call.assert_called_once_with(100500) + + + def test_mock_service_call_object(self) -> None: + expected = 'foo' + rpc = SomeService() + + mock.patch.object( + rpc, + 'service_call', + return_value=expected, + autospec=True) + + self.assertEqual(interact_with_service(rpc, expected), expected) + diff --git a/python/unittest/tests/test_thing.py b/python/unittest/tests/test_thing.py new file mode 100644 index 00000000..7d6f94e8 --- /dev/null +++ b/python/unittest/tests/test_thing.py @@ -0,0 +1,13 @@ +from app.thing import Thing +import unittest + +class TestThing(unittest.TestCase): + + def test_correct_greeting(self): + thing = Thing("Bob") + self.assertEqual("Hello Bob!", thing.return_hello_name()) + + + def test_fail(self): + thing = Thing("Albert") + self.assertEqual("Wrong!", thing.return_hello_name()) diff --git a/python/unittest/tests/test_thing_fixture.py b/python/unittest/tests/test_thing_fixture.py new file mode 100644 index 00000000..37cec49d --- /dev/null +++ b/python/unittest/tests/test_thing_fixture.py @@ -0,0 +1,14 @@ +import unittest +from app.thing import Thing + +class TestThingFixture(unittest.TestCase): + def setUp(self): + self.thing=Thing("Bob") + + def test_correct_greeting(self): + self.assertEqual("Hello Bob!", self.thing.return_hello_name()) + + + def test_fail(self): + self.assertEqual("Wrong!", self.thing.return_hello_name()) + diff --git a/python/unittest/todo_project_name_test.py b/python/unittest/todo_project_name_test.py deleted file mode 100644 index 6c4d5196..00000000 --- a/python/unittest/todo_project_name_test.py +++ /dev/null @@ -1,7 +0,0 @@ -import unittest - - -class TodoProjectNameTestCase(unittest.TestCase): - - def test_python_test_setup_works(self): - self.assertEqual(42, 43)