Skip to content

Commit 1916012

Browse files
committed
Update python testing exericse
1 parent b660f6b commit 1916012

1 file changed

Lines changed: 10 additions & 27 deletions

File tree

05_testing_and_ci/python_testing_exercise.md

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
## Starting Remarks
44

5-
- [Exercise repository link](https://github.com/Simulation-Software-Engineering/testing-python-exercise-wt2425)
6-
- Deadline for submitting this exercise is **Wednesday 22nd January 2025 09:00**.
5+
- [Exercise repository link](https://github.com/Simulation-Software-Engineering/testing-python-exercise)
6+
- Deadline for submitting this exercise is **Wednesday 21st January 2026 09:00**.
77

88
## Prerequisites
99

@@ -32,13 +32,13 @@
3232

3333
## Step 2 - Adding Assertion Statements
3434

35-
- Add assertion statements to the functions `initialize_domain` and `initialize_physical_parameters` which check whether all input parameters have type `float`.
35+
- Add assertion statements to the functions `initialize_domain` and `initialize_physical_parameters` which check whether all input parameters are double precision/floats.
3636
- Rerun the code after inserting all the assertion statements? Does the code break? Which parameters are problematic?
3737
- The default values of some of the input parameters like `T_hot` and `T_cold` are in fact integers and need to be changed. Change these values to floats and rerun the code to make sure that all assertions are returning true.
3838

3939
## Step 3 - Writing Unit Tests
4040

41-
- Now you will write all the tests in a way that they can be run using `pytest`.
41+
- Write unit tests using either pytest or unittest.
4242
- In the repository there is a folder `tests/`. In this folder there are two folders `unit/` and `integration/`. The first tests written will be unit tests.
4343
- In the file `tests/unit/test_diffusion2d_functions.py` there is already a skeleton code for three unit tests which are to be implemented. The name of each test is of the format `test_<name_of_function_being_tested>`.
4444
- As these are unit tests, in each test, only the call to the respective function needs to be made. No other function from `diffusion2d.py` must be called. If another function call is required to define some member variables, it can be evaded by directly defining the member variables in the test. All the member variables can be accessed directly using the class object.
@@ -48,39 +48,26 @@
4848
- Now call the function `initialize_domain` with the chosen values of `w`, `h`, `dx`, and `dy` and using an assertion statement, check if the values of `nx` and `ny` in the class member variables are equal to your expected values.
4949
- Note that you have the object of the class `SolveDiffusion2D` and hence you can access member variables, for example `solver.nx` and `solver.ny`. This is useful to check the actual values.
5050
- Using a similar workflow, complete the other two unit tests.
51-
- Run the tests using `pytest`.
52-
- It is observed that in some instances `pytest` is not able to find the tests. One reason is the way pytest is installed, which is typically either using `pip` or `apt`. Refer to the [corresponding section](https://github.com/Simulation-Software-Engineering/Lecture-Material/blob/main/05_testing_and_ci/python_testing_demo.md#pytest) in the demo for more details. If such errors occur, then try to explicitly point pytest to the relevant test file in the following way:
51+
- It is observed that in some instances pytest is not able to find the tests. One reason is the way pytest is installed, which is typically either using pip or apt. Refer to the [corresponding section](https://github.com/Simulation-Software-Engineering/Lecture-Material/blob/main/05_testing_and_ci/python_testing_demo.md#pytest) in the demo for more details. If such errors occur, then try to explicitly point pytest to the relevant test file in the following way:
5352

5453
```bash
5554
pytest tests/unit/test_diffusion2d_functions.py
5655
```
5756

58-
- If everything is done correctly, then after running `pytest` all the tests should pass.
57+
- If everything is done correctly, all the tests should pass.
5958
- How can you make sure that you have written correct tests? By breaking them purposely!
6059
- Introduce a bug in a function on purpose and then re-run the test to see if the test fails.
6160
- Lets try this in the function `initialize_domain`. In line 42 of `diffusion2d.py`, change the calculation from `self.nx = int(w / dx)` to `self.nx = int(h / dx)`. This is clearly a mistake and our test should catch it.
62-
- Now re-run pytest. Did the test catch the bug? If yes, then you have written the test correctly. If the test does not catch the bug, try to think why did it not? Is your choice of values for the parameters `w`, `h`, `dx` and `dy` responsible for it? If the test is run with `w = h` then this bug will not be caught. What do we learn from this? We learn that the test fixture should be as general as possible and we should ensure that we are not testing special scenarios. A domain with `w = h` is a square domain which is a special case of a rectangular domain with arbitrary values for `w` and `h`.
63-
- **Important step**: A failing test in pytest will produce an output log in the terminal. Copy this output log in a code block in the `README.md` file under the section *pytest log*. This log output will be part of the submission and hence is important.
64-
- Purposely break all the unit tests and copy the failing tests logs into the aforementioned section in the README file.
65-
- Before moving on from this step, make sure that you have reverted all the intentionally introduced bugs in the original code.
61+
- Now run the tests again. Did the test catch the bug? If yes, then you have written the test correctly. If the test does not catch the bug, try to think why did it not? Is your choice of values for the parameters `w`, `h`, `dx` and `dy` responsible for it? If the test is run with `w = h` then this bug will not be caught. What do we learn from this? We learn that the test fixture should be as general as possible and we should ensure that we are not testing special scenarios. A domain with `w = h` is a square domain which is a special case of a rectangular domain with arbitrary values for `w` and `h`.
6662

67-
## Step 4 - Writing Unit Tests Using unittest
68-
69-
- Now you will write all the tests in a way that they can be run using `unittest`.
70-
- Modify the unit tests written in the previous section to be run with unittest. This is done in the same file `tests/unit/test_diffusion2d_functions.py`.
71-
- Start by creating a class `TestDiffusion2D` which is derived from the class `unittest.TestCase`. Migrate all the tests inside the class and change them to be member functions of the class. Note that the parameter `self` needs to be used in the input parameters of all member functions and also while defining and using member variables.
72-
- The tests themselves will not change. The same functions will be tested in the same way, just with the `unittest` framework.
63+
- If you are writing tests with unittest, start by creating a class `TestDiffusion2D` which is derived from the class `unittest.TestCase`. Migrate all the tests inside the class and change them to be member functions of the class. Note that the parameter `self` needs to be used in the input parameters of all member functions and also while defining and using member variables.
7364
- Identify the common steps necessary in all the tests and transfer the functionality to the function `setUp`. One example of this is the definition of the object of class `SolveDiffusion2D`.
7465
- The main change is in the assertion statements. Change the assertion statements to the format as required by `unittest`. Refer to the lecture demo for an example on how to do this.
7566
- Using the same logic as in the previous step, intentionally break the tests to make sure that the tests are constructed correctly.
76-
- **Important step**: A failing test in unittest will produce an output log in the terminal. Copy this output log in a code block in the README file under the section *unittest log*. This log output will be part of the submission and hence is important.
77-
- Purposely break all the unit tests and copy the failing tests logs into the aforementioned section in the README file.
78-
- Before moving on from the unit tests, make sure that you have reverted all the intentionally introduced bugs in the original code.
7967

8068
## Step 5 - Writing Integration Tests
8169

82-
- You will now write integration tests for this code **using pytest**. The integration tests will be written in the file `tests/integration/test_diffusion2d.py`.
83-
- Integration tests will be written for the functions `initialize_physical_parameters` and `set_initial_conditions`. As these are integration tests, each test should check how different functions from `SolveDiffusion2D` work together.
70+
- Write integration tests will be written for the functions `initialize_physical_parameters` and `set_initial_conditions`. As these are integration tests, each test should check how different functions from `SolveDiffusion2D` work together.
8471
- For example, let us look at how the test for `initialize_physical_parameters` will look like.
8572
- First step is to select some values for the input parameters to the function `initialize_physical_parameters` and also the function `initialize_domain`.
8673
- Looking at the functionality in `initialize_physical_parameters` we understand that the most relevant variable being calculated is `dt`.
@@ -89,19 +76,15 @@ pytest tests/unit/test_diffusion2d_functions.py
8976
- Compare the value of the member variable `dt` with the manually computed `dt` using an assertion statement.
9077
- Now also write a similar integration test for `set_initial_conditions`. Note that this will be the most extensive test from the whole set. The field variable `u` is computed in `set_initial_conditions`, which is a 2D array. The test should have a computation which computes a similar `u` array for a user-defined set of initial parameters. This computed `u` is the expected result.
9178
- Using the same logic as in the previous steps, intentionally break the tests to make sure that the tests are constructed correctly.
92-
- **Important step**: A failing test in integration test will produce an output log in the terminal. Copy this output log in a code block in the `README.md` file under the section *Integration test log*. This log output will be part of the submission and hence is important.
93-
- Purposely break all the integration tests and copy the failing tests logs into the aforementioned section in the README file.
94-
- Before moving on from the integration tests, make sure that you have reverted all the intentionally introduced bugs in the original code.
9579

9680
## Step 6 - Checking Test Coverage
9781

9882
- Using the coverage tool generate a HTML report of the code coverage of all the tests.
9983
- Open the report file in a browser and print the report to a file called `coverage-report.pdf`. Add this file to the repository.
100-
- **Note**: coverage can be used with both `pytest` and `unittest`. In this case, generating the report of the unit tests using unittest is sufficient.
10184

10285
## Step 7 - Automation Using tox
10386

104-
- Write a `tox.toml` file such that by running the command `tox`, both `pytest` and `unittest` are executed.
87+
- Write a `tox.toml` file such that by running the command `tox`, the tests are run using pytest and/or unittest in separate virtual environments.
10588
- Use the `requirements.txt` file to send all the dependencies information to tox.
10689

10790
## Step 8 - Submission

0 commit comments

Comments
 (0)