From 430677efedb43264bde6cf93328e456e978876b2 Mon Sep 17 00:00:00 2001 From: Greg Gorlen Date: Mon, 13 Jun 2022 15:32:54 -0700 Subject: [PATCH 1/3] Add Python unittest --- content/languages/python/index.md | 2 +- content/languages/python/unittest.mdx | 64 +++++++++++++++++++++++++++ sidebars.js | 1 + 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 content/languages/python/unittest.mdx diff --git a/content/languages/python/index.md b/content/languages/python/index.md index d60f6fc1..d2d9eab7 100644 --- a/content/languages/python/index.md +++ b/content/languages/python/index.md @@ -13,7 +13,7 @@ slug: /languages/python ## Test Frameworks - [Codewars Test Framework](/languages/python/codewars-test) -- unittest +- [unittest](/languages/python/unittest) ## Timeout 12 seconds diff --git a/content/languages/python/unittest.mdx b/content/languages/python/unittest.mdx new file mode 100644 index 00000000..f2f30adf --- /dev/null +++ b/content/languages/python/unittest.mdx @@ -0,0 +1,64 @@ +--- +title: Python unittest +sidebar_label: unittest +kind: reference +--- + +import ThemedImage from "@theme/ThemedImage"; + +Codewars offers Python's [unittest](https://docs.python.org/3/library/unittest.html) module for testing solutions. Codewars uses a custom reporter for unittest to format the output for the code runner. Visit the [python-test-framework](https://github.com/codewars/python-unittest) GitHub repository for more information. + +## Basic Example + +```python +import solution +import unittest +from codewars_unittest import CodewarsTestRunner + +class TestBasicFunctionality(unittest.TestCase): + def test_add(self): + "add two numbers" + self.assertEqual(solution.add(2, 1), 3) + + def test_subtract(self): + "subtract two numbers" + self.assertEqual(solution.subtract(2, 1), 1) + +class TestEdgeCases(unittest.TestCase): + def test_division_by_zero(self): + "divide by zero" + self.assertRaises(ZeroDivisionError, solution.divide, 42, 0) + +unittest.main(testRunner=CodewarsTestRunner()) +``` + +As demonstrated above, methods intended to be tested must begin with the prefix `test`. The `Test` class name is flexible. You may register multiple classes before invoking `unittest.main`. Verbose test descriptions can be provided with a simple [docstring](https://www.python.org/dev/peps/pep-0257/). + +Visit [unittest — Basic Example](https://docs.python.org/3/library/unittest.html#basic-example) for a simple, platform-agnostic example of `unittest`. + +## Assertions + +The crux of each test is a call to [`assertEqual()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertEqual) to check for an expected result; [`assertTrue()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue) or [`assertFalse()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertFalse) to verify a condition; or [`assertRaises()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises) to verify that a specific exception gets raised. These methods are used instead of the `assert` statement so the test runner can accumulate all test results and produce a report. + +## Setup and Tear Down + +The [`setUp()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUp) and [`tearDown()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.tearDown) methods allow you to execute code before and after each test method. + +Similarly, you can use [`setUpClass()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.setUpClass) and [`tearDownClass()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.tearDownClass) to run code before all tests run and after all tests complete, respectively. + +## Test Ordering + +Unittest reorders test cases by default which can cause frustration for candidates and students when matching test case code with the output displayed on the runner. There are a variety of solutions to the problem which you can read about on [this Stack Overflow thread](https://stackoverflow.com/questions/5387299/python-unittest-testcase-execution-order), but the following approach should work for typical cases: + +```python +import inspect + +class Test(unittest.TestCase): + # ... test cases ... + +test_src = inspect.getsource(Test) +unittest.TestLoader.sortTestMethodsUsing = lambda _, x, y: ( + test_src.index(f"def {x}") - test_src.index(f"def {y}") +) +``` + diff --git a/sidebars.js b/sidebars.js index 4a8befdd..ae0a86ad 100644 --- a/sidebars.js +++ b/sidebars.js @@ -357,6 +357,7 @@ module.exports = { "languages/python/index", "languages/python/authoring", "languages/python/codewars-test", + "languages/python/unittest", ], }, { From 9c8c28a4044ab6b5c9892b59e54baf012060eb20 Mon Sep 17 00:00:00 2001 From: Greg Gorlen Date: Mon, 13 Jun 2022 15:37:21 -0700 Subject: [PATCH 2/3] Add Python 3.10 version --- content/languages/python/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/content/languages/python/index.md b/content/languages/python/index.md index d2d9eab7..9c9f914d 100644 --- a/content/languages/python/index.md +++ b/content/languages/python/index.md @@ -9,6 +9,7 @@ slug: /languages/python - 3.6 - 3.8 +- 3.10 ## Test Frameworks From b956c574cb34de3587d4eb3f04076f4f2ca3b0ab Mon Sep 17 00:00:00 2001 From: Greg Gorlen Date: Mon, 13 Jun 2022 15:38:57 -0700 Subject: [PATCH 3/3] Add comma --- content/languages/python/unittest.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/languages/python/unittest.mdx b/content/languages/python/unittest.mdx index f2f30adf..2698d28a 100644 --- a/content/languages/python/unittest.mdx +++ b/content/languages/python/unittest.mdx @@ -38,7 +38,7 @@ Visit [unittest — Basic Example](https://docs.python.org/3/library/unittest.ht ## Assertions -The crux of each test is a call to [`assertEqual()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertEqual) to check for an expected result; [`assertTrue()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue) or [`assertFalse()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertFalse) to verify a condition; or [`assertRaises()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises) to verify that a specific exception gets raised. These methods are used instead of the `assert` statement so the test runner can accumulate all test results and produce a report. +The crux of each test is a call to [`assertEqual()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertEqual) to check for an expected result; [`assertTrue()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertTrue) or [`assertFalse()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertFalse) to verify a condition; or [`assertRaises()`](https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertRaises) to verify that a specific exception gets raised. These methods are used instead of the `assert` statement, so the test runner can accumulate all test results and produce a report. ## Setup and Tear Down