From 7e487a81b4997b08e8321689207bafe374bbb483 Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 13:52:03 +0000 Subject: [PATCH 1/8] assert for `result.summary` at `testTemplateMethod()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change will enable us to display a visual report of the tests being run, so we can give feedback to users (instead of the program just blankly finishing) Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results 👈🏼 --- Output: ➜ python3 src/test_case_test.py Traceback (most recent call last): File "tdd-xunit-example/src/test_case_test.py", line 12, in TestCaseTest("testTemplateMethod").run() File "tdd-xunit-example/src/test_case.py", line 12, in run method() File "tdd-xunit-example/src/test_case_test.py", line 9, in testTemplateMethod assert ("1 run, 0 failed" == result.summary()) ^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'summary' --- src/test_case_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test_case_test.py b/src/test_case_test.py index d02e0c0..a96a2a2 100644 --- a/src/test_case_test.py +++ b/src/test_case_test.py @@ -5,8 +5,8 @@ class TestCaseTest(TestCase): def testTemplateMethod(self) -> None: test = WasRun("testMethod") - test.run() - assert ("setUp testMethod tearDown " == test.log) + result = test.run() + assert ("1 run, 0 failed" == result.summary()) TestCaseTest("testTemplateMethod").run() From 2475871410ac2adc99afd96401f35d9889dec38a Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 13:54:58 +0000 Subject: [PATCH 2/8] introduce a `TestResult` class with hardcoded impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This class will be used to hold a summary of the test suite execution. For now, though, it's just implementing a summary method with a hardcoded implementation. Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results 👈🏼 --- Output: ➜ python3 src/test_case_test.py Traceback (most recent call last): File "tdd-xunit-example/src/test_case_test.py", line 12, in TestCaseTest("testTemplateMethod").run() File "tdd-xunit-example/src/test_case.py", line 12, in run method() File "tdd-xunit-example/src/test_case_test.py", line 9, in testTemplateMethod assert ("1 run, 0 failed" == result.summary()) ^^^^^^^^^^^^^^ AttributeError: 'NoneType' object has no attribute 'summary' --- src/test_result.py | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/test_result.py diff --git a/src/test_result.py b/src/test_result.py new file mode 100644 index 0000000..e081e68 --- /dev/null +++ b/src/test_result.py @@ -0,0 +1,3 @@ +class TestResult: + def summary(self): + return "1 run, 0 failed" From e744108a6c015959aae6588a7beef0b664b20935 Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 13:56:33 +0000 Subject: [PATCH 3/8] return an instance of `TestResult` at `TestCase.run()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results 👈🏼 --- src/test_case.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test_case.py b/src/test_case.py index 3947f15..88ba2be 100644 --- a/src/test_case.py +++ b/src/test_case.py @@ -1,3 +1,6 @@ +from test_result import TestResult + + class TestCase: def __init__(self, name) -> None: @@ -11,6 +14,7 @@ def run(self) -> None: method = getattr(self, self.name) method() self.tearDown() + return TestResult() def tearDown(self) -> None: pass From 4334eaf73ce23ce1df2454582ae61bd5847232d1 Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 13:58:10 +0000 Subject: [PATCH 4/8] introduce symbolic constant `runCount` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This instance variable will be used to hold the number of tests there were ran in a test session. For now, though, it is hardcoded to the value 1. Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results 👈🏼 --- src/test_result.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test_result.py b/src/test_result.py index e081e68..d4ea364 100644 --- a/src/test_result.py +++ b/src/test_result.py @@ -1,3 +1,6 @@ class TestResult: + def __init__(self) -> None: + self.runCount = 1 + def summary(self): - return "1 run, 0 failed" + return "%d run, 0 failed" % self.runCount From 69d2a119e30119eeca632d4a4b828199c2f2426e Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 14:00:55 +0000 Subject: [PATCH 5/8] implement `testStarted()` at `TestResult` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This method will be responsible for updating the value of runCount everytime a test is executed Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results 👈🏼 --- Output: ➜ python3 src/test_case_test.py Traceback (most recent call last): File "tdd-xunit-example/src/test_case_test.py", line 12, in TestCaseTest("testTemplateMethod").run() File "tdd-xunit-example/src/test_case.py", line 15, in run method() File "tdd-xunit-example/src/test_case_test.py", line 9, in testTemplateMethod assert ("1 run, 0 failed" == result.summary()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AssertionError --- src/test_result.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test_result.py b/src/test_result.py index d4ea364..ed379dc 100644 --- a/src/test_result.py +++ b/src/test_result.py @@ -1,6 +1,9 @@ class TestResult: def __init__(self) -> None: - self.runCount = 1 + self.runCount = 0 + + def testStarted(self) -> None: + self.runCount = self.runCount + 1 def summary(self): return "%d run, 0 failed" % self.runCount From 5d7469ba3ba13c222ae14bc5615d5cdc43457513 Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 14:03:06 +0000 Subject: [PATCH 6/8] update `TestCase.run()` to call `TestResult.testStarted()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This call is needed so we can increment the runCount variable and compute the number of tests ran in a session Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results 👈🏼 --- src/test_case.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test_case.py b/src/test_case.py index 88ba2be..1a72afc 100644 --- a/src/test_case.py +++ b/src/test_case.py @@ -10,11 +10,13 @@ def setUp(self) -> None: pass def run(self) -> None: + result = TestResult() + result.testStarted() self.setUp() method = getattr(self, self.name) method() self.tearDown() - return TestResult() + return result def tearDown(self) -> None: pass From 751d37d735c67f1c9f4bf17bd6b995ae3ab74ccd Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 14:05:42 +0000 Subject: [PATCH 7/8] add test for a failed test report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results 👈🏼 --- Output: ➜ python3 src/test_case_test.py Traceback (most recent call last): File "tdd-xunit-example/src/test_case_test.py", line 18, in TestCaseTest("testFailedResult").run() File "tdd-xunit-example/src/test_case.py", line 17, in run method() File "tdd-xunit-example/src/test_case_test.py", line 13, in testFailedResult result = test.run() ^^^^^^^^^^ File "tdd-xunit-example/src/test_case.py", line 16, in run method = getattr(self, self.name) ^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'WasRun' object has no attribute 'testBrokenMethod' --- src/test_case_test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test_case_test.py b/src/test_case_test.py index a96a2a2..78ddd10 100644 --- a/src/test_case_test.py +++ b/src/test_case_test.py @@ -8,5 +8,11 @@ def testTemplateMethod(self) -> None: result = test.run() assert ("1 run, 0 failed" == result.summary()) + def testFailedResult(self) -> None: + test = WasRun("testBrokenMethod") + result = test.run() + assert ("1 run, 1 failed" == result.summary()) + TestCaseTest("testTemplateMethod").run() +TestCaseTest("testFailedResult").run() From 47adee2f59fefb5517b5672f64f873c70f05c618 Mon Sep 17 00:00:00 2001 From: Kaio Silveira Date: Sat, 18 Mar 2023 14:08:57 +0000 Subject: [PATCH 8/8] implement `testBrokenMethod()` at `WasRun` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This implementation will support the code being executed as part of TestCase.testFailedResult. For now, though, we're just raising an exception. Checklist: - Invoke tearDown even if the test method fails - Run multiple tests - Report collected results ✅ --- Output: ➜ python3 src/test_case_test.py Traceback (most recent call last): File "tdd-xunit-example/src/test_case_test.py", line 18, in TestCaseTest("testFailedResult").run() File "tdd-xunit-example/src/test_case.py", line 17, in run method() File "tdd-xunit-example/src/test_case_test.py", line 13, in testFailedResult result = test.run() ^^^^^^^^^^ File "tdd-xunit-example/src/test_case.py", line 17, in run method() File "tdd-xunit-example/src/was_run.py", line 20, in testBrokenMethod raise Exception Exception --- src/was_run.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/was_run.py b/src/was_run.py index fa62637..56e1198 100644 --- a/src/was_run.py +++ b/src/was_run.py @@ -15,3 +15,6 @@ def testMethod(self) -> None: def tearDown(self) -> None: self.log = self.log + "tearDown " + + def testBrokenMethod(self) -> None: + raise Exception