diff --git a/README.md b/README.md index da66993c..56eec4c7 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,513 @@ Please follow the instructions in [python_testing_exercise.md](https://github.co ## Test logs (for submission) ### pytest log +(After swapping `w` for `h` in the calculation of `nx`) +``` +============================= test session starts ============================== +collecting ... collected 6 items + +integration/test_diffusion2d.py::test_initialize_physical_parameters +integration/test_diffusion2d.py::test_set_initial_condition +unit/test_diffusion2d_functions.py::test_initialize_domain PASSED [ 16%]PASSED [ 33%] +unit/test_diffusion2d_functions.py::test_initialize_domain_testcase_2 +unit/test_diffusion2d_functions.py::test_initialize_physical_parameters +unit/test_diffusion2d_functions.py::test_set_initial_condition + +========================= 2 failed, 4 passed in 0.22s ========================== +FAILED [ 50%] +unit/test_diffusion2d_functions.py:9 (test_initialize_domain) +5 != 10 + +Expected :10 +Actual :5 + + +def test_initialize_domain(): + """ + Check function SolveDiffusion2D.initialize_domain + """ + solver = SolveDiffusion2D() + # Arrange test values + w = 20. + h = 10. + dx = 2. + dy = 0.2 + + # Act (= Perform test action) + solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + assert solver.w == w + assert solver.h == h + assert solver.dx == dx + assert solver.dy == dy + # Calculated values +> assert solver.nx == 10 +E assert 5 == 10 +E + where 5 = .nx + +unit/test_diffusion2d_functions.py:31: AssertionError +FAILED [ 66%] +unit/test_diffusion2d_functions.py:34 (test_initialize_domain_testcase_2) +6 != 5 + +Expected :5 +Actual :6 + + +def test_initialize_domain_testcase_2(): + """ + Second testcase for function SolveDiffusion2D.initialize_domain + """ + solver = SolveDiffusion2D() + # Arrange test values + # "unschöne" values + w = 15.2 + h = 17.1 + dx = 2.7 + dy = 0.29 + + # Act (= Perform test action) + solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + assert solver.w == w + assert solver.h == h + assert solver.dx == dx + assert solver.dy == dy + # Calculated values +> assert solver.nx == 5 +E assert 6 == 5 +E + where 6 = .nx + +unit/test_diffusion2d_functions.py:57: AssertionError +PASSED [ 83%]dt = 0.0011428571428571432 +PASSED [100%] +Process finished with exit code 1 +``` + +(After changing the formula for `dt`: `dx2, dy2 = self.dx * self.dy, self.dx * self.dy`) +``` +============================= test session starts ============================== +collecting ... collected 6 items + +integration/test_diffusion2d.py::test_initialize_physical_parameters PASSED [ 16%] +integration/test_diffusion2d.py::test_set_initial_condition PASSED [ 33%] +unit/test_diffusion2d_functions.py::test_initialize_domain PASSED [ 50%] +unit/test_diffusion2d_functions.py::test_initialize_domain_testcase_2 PASSED [ 66%] +unit/test_diffusion2d_functions.py::test_initialize_physical_parameters FAILED [ 83%]dt = 0.001428571428571429 + +unit/test_diffusion2d_functions.py:60 (test_initialize_physical_parameters) +0.001428571428571429 != 0.001142 ± 1.0e-06 + +Expected :0.001142 ± 1.0e-06 +Actual :0.001428571428571429 + + +def test_initialize_physical_parameters(): + """ + Checks function SolveDiffusion2D.initialize_domain + """ + solver = SolveDiffusion2D() + # Arrange + d = 3.5 + T_cold = 342.4 + T_hot = 723.15 + solver.dx = 0.1 + solver.dy = 0.2 + + # Act + solver.initialize_physical_parameters(d, T_cold, T_hot) + + # Assert + assert solver.D == d + assert solver.T_cold == T_cold + assert solver.T_hot == T_hot +> assert solver.dt == pytest.approx(0.001142, abs=1e-6) +E assert 0.001428571428571429 == 0.001142 ± 1.0e-06 +E +E comparison failed +E Obtained: 0.001428571428571429 +E Expected: 0.001142 ± 1.0e-06 + +unit/test_diffusion2d_functions.py:80: AssertionError + +unit/test_diffusion2d_functions.py::test_set_initial_condition PASSED [100%] + +========================= 1 failed, 5 passed in 0.22s ========================== + +Process finished with exit code 1 +``` + +(After introducing an error into `set_initial_condition` (wrong shape): `u = self.T_cold * np.ones((self.nx, self.nx))`) +``` +============================= test session starts ============================== +collecting ... collected 6 items + +integration/test_diffusion2d.py::test_initialize_physical_parameters +integration/test_diffusion2d.py::test_set_initial_condition +unit/test_diffusion2d_functions.py::test_initialize_domain PASSED [ 16%]PASSED [ 33%] +unit/test_diffusion2d_functions.py::test_initialize_domain_testcase_2 +unit/test_diffusion2d_functions.py::test_initialize_physical_parameters +unit/test_diffusion2d_functions.py::test_set_initial_condition + +========================= 1 failed, 5 passed in 0.22s ========================== +PASSED [ 50%]PASSED [ 66%]PASSED [ 83%]dt = 0.0007142857142857145 +FAILED [100%] +unit/test_diffusion2d_functions.py:82 (test_set_initial_condition) +100 != 50 + +Expected :50 +Actual :100 + + +def test_set_initial_condition(): + """ + Checks function SolveDiffusion2D.get_initial_function + """ + solver = SolveDiffusion2D() + # Arrange + solver.nx = 100 + solver.ny = 50 + solver.dx = 0.1 + solver.dy = 0.2 + solver.T_cold = 100. + solver.T_hot = 600. + + # Act + u: np.ndarray = solver.set_initial_condition() + + # Assert + # Domain has expected dimensions + assert u.shape[0] == solver.nx +> assert u.shape[1] == solver.ny +E assert 100 == 50 +E + where 50 = .ny + +unit/test_diffusion2d_functions.py:102: AssertionError + +Process finished with exit code 1 +``` + +(After introducing an error into `set_initial_condition` (inverse values): `if not p2 < r2:`) +``` +============================= test session starts ============================== +collecting ... collected 6 items + +integration/test_diffusion2d.py::test_initialize_physical_parameters +integration/test_diffusion2d.py::test_set_initial_condition +unit/test_diffusion2d_functions.py::test_initialize_domain PASSED [ 16%]PASSED [ 33%] +unit/test_diffusion2d_functions.py::test_initialize_domain_testcase_2 +unit/test_diffusion2d_functions.py::test_initialize_physical_parameters +unit/test_diffusion2d_functions.py::test_set_initial_condition + +========================= 1 failed, 5 passed in 0.21s ========================== +PASSED [ 50%]PASSED [ 66%]PASSED [ 83%]dt = 0.0007142857142857145 +FAILED [100%] +unit/test_diffusion2d_functions.py:82 (test_set_initial_condition) +np.float64(600.0) != 100.0 + +Expected :100.0 +Actual :np.float64(600.0) + + +def test_set_initial_condition(): + """ + Checks function SolveDiffusion2D.get_initial_function + """ + solver = SolveDiffusion2D() + # Arrange + solver.nx = 100 + solver.ny = 50 + solver.dx = 0.1 + solver.dy = 0.2 + solver.T_cold = 100. + solver.T_hot = 600. + + # Act + u: np.ndarray = solver.set_initial_condition() + + # Assert + # Domain has expected dimensions + assert u.shape[0] == solver.nx + assert u.shape[1] == solver.ny + # Border is cold, center is hot +> assert u[0][0] == 100. +E assert np.float64(600.0) == 100.0 + +unit/test_diffusion2d_functions.py:104: AssertionError + +Process finished with exit code 1 +``` ### unittest log +(After swapping `w` for `h` in the calculation of `nx`) +``` +============================= test session starts ============================== +collecting ... collected 4 items + +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_domain FAILED [ 25%] +test_diffusion2d_functions.py:16 (TestDiffusion2D.test_initialize_domain) +10 != 5 + +Expected :5 +Actual :10 + + +self = + + def test_initialize_domain(self): + """ + Check function SolveDiffusion2D.initialize_domain + """ + # Arrange test values + w = 20. + h = 10. + dx = 2. + dy = 0.2 + + # Act (= Perform test action) + self.solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + self.assertEqual(self.solver.w, w) + self.assertEqual(self.solver.h, h) + self.assertEqual(self.solver.dx, dx) + self.assertEqual(self.solver.dy, dy) + # Calculated values +> self.assertEqual(self.solver.nx, 10) + +test_diffusion2d_functions.py:37: AssertionError + +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_domain_testcase_2 FAILED [ 50%] +test_diffusion2d_functions.py:39 (TestDiffusion2D.test_initialize_domain_testcase_2) +5 != 6 + +Expected :6 +Actual :5 + + +self = + + def test_initialize_domain_testcase_2(self): + """ + Second testcase for function SolveDiffusion2D.initialize_domain + """ + # Arrange test values + # "unschöne" values + w = 15.2 + h = 17.1 + dx = 2.7 + dy = 0.29 + + # Act (= Perform test action) + self.solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + self.assertEqual(self.solver.w, w) + self.assertEqual(self.solver.h, h) + self.assertEqual(self.solver.dx, dx) + self.assertEqual(self.solver.dy, dy) + # Calculated values +> self.assertEqual(self.solver.nx, 5) + +test_diffusion2d_functions.py:61: AssertionError + +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_physical_parameters PASSED [ 75%]dt = 0.0011428571428571432 + +test_diffusion2d_functions.py::TestDiffusion2D::test_set_initial_condition PASSED [100%] + +========================= 2 failed, 2 passed in 0.21s ========================== + +Process finished with exit code 1 +``` + +(After changing the formula for `dt`: `dx2, dy2 = self.dx * self.dy, self.dx * self.dy`) +``` +============================= test session starts ============================== +collecting ... collected 4 items + +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_domain PASSED [ 25%] +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_domain_testcase_2 PASSED [ 50%] +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_physical_parameters FAILED [ 75%]dt = 0.001428571428571429 + +test_diffusion2d_functions.py:63 (TestDiffusion2D.test_initialize_physical_parameters) +self = + + def test_initialize_physical_parameters(self): + """ + Checks function SolveDiffusion2D.initialize_domain + """ + # Arrange + d = 3.5 + T_cold = 342.4 + T_hot = 723.15 + self.solver.dx = 0.1 + self.solver.dy = 0.2 + + # Act + self.solver.initialize_physical_parameters(d, T_cold, T_hot) + + # Assert + self.assertEqual(self.solver.D, d) + self.assertEqual(self.solver.T_cold, T_cold) + self.assertEqual(self.solver.T_hot, T_hot) + # unittest assumes rounding here, so the last decimal differs from pytest. +> self.assertAlmostEqual(self.solver.dt, 0.001143, 6) +E AssertionError: 0.001428571428571429 != 0.001143 within 6 places (0.0002855714285714291 difference) + +test_diffusion2d_functions.py:83: AssertionError + +test_diffusion2d_functions.py::TestDiffusion2D::test_set_initial_condition PASSED [100%] + +========================= 1 failed, 3 passed in 0.22s ========================== + +Process finished with exit code 1 +``` + +(After introducing an error into `set_initial_condition` (inverse values): `if not p2 < r2:`) +``` +============================= test session starts ============================== +collecting ... collected 4 items + +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_domain +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_domain_testcase_2 +test_diffusion2d_functions.py::TestDiffusion2D::test_initialize_physical_parameters +test_diffusion2d_functions.py::TestDiffusion2D::test_set_initial_condition + +========================= 1 failed, 3 passed in 0.22s ========================== +PASSED [ 25%]PASSED [ 50%]PASSED [ 75%]dt = 0.0011428571428571432 +FAILED [100%] +test_diffusion2d_functions.py:84 (TestDiffusion2D.test_set_initial_condition) +100.0 != np.float64(600.0) + +Expected :np.float64(600.0) +Actual :100.0 + + +self = + + def test_set_initial_condition(self): + """ + Checks function SolveDiffusion2D.get_initial_function + """ + # Arrange + self.solver.nx = 100 + self.solver.ny = 50 + self.solver.dx = 0.1 + self.solver.dy = 0.2 + self.solver.T_cold = 100. + self.solver.T_hot = 600. + + # Act + u: np.ndarray = self.solver.set_initial_condition() + + # Assert + # Domain has expected dimensions + self.assertEqual(u.shape[0], self.solver.nx) + self.assertEqual(u.shape[1], self.solver.ny) + # Border is cold, center is hot +> self.assertEqual(u[0][0], 100.) + +test_diffusion2d_functions.py:105: AssertionError + +Process finished with exit code 1 +``` + +### pytest-log for Integration-Tests + +(breaking `test_initialize_physical_parameters` by taking `dx2*dx2`) +``` +============================= test session starts ============================== +collecting ... collected 1 item + +test_diffusion2d.py::test_initialize_physical_parameters FAILED [100%]dt = 0.006666666666666669 + +test_diffusion2d.py:8 (test_initialize_physical_parameters) +0.006666666666666669 != 0.001666 ± 1.0e-06 + +Expected :0.001666 ± 1.0e-06 +Actual :0.006666666666666669 + + +def test_initialize_physical_parameters(): + """ + Checks function SolveDiffusion2D.initialize_domain + """ + solver = SolveDiffusion2D() + solver.initialize_domain(10., 20., 0.2, 0.1) + solver.initialize_physical_parameters(2.4, 0., 1.) + # dx2 = 0.04 + # dy2 = 0.01 + # dt = 0.0004 / (2*2.4*0.05) = 1/600 = 0.0016666 +> assert solver.dt == pytest.approx(0.001666, abs=1e-6) +E assert 0.006666666666666669 == 0.001666 ± 1.0e-06 +E +E comparison failed +E Obtained: 0.006666666666666669 +E Expected: 0.001666 ± 1.0e-06 + +test_diffusion2d.py:19: AssertionError + + +============================== 1 failed in 0.21s =============================== + +Process finished with exit code 1 +``` + +(breaking `test_set_initial_condition` by cubing instead of squaring) +``` +============================= test session starts ============================== +collecting ... collected 1 item + +test_diffusion2d.py::test_set_initial_condition FAILED [100%]dt = 0.09259259259259259 + +test_diffusion2d.py:21 (test_set_initial_condition) +0.0 != np.float64(1.0) + +Expected :np.float64(1.0) +Actual :0.0 + + +def test_set_initial_condition(): + """ + Checks function SolveDiffusion2D.get_initial_function + """ + solver = SolveDiffusion2D() + solver.initialize_domain(10., 10., 1., 1.) + solver.initialize_physical_parameters(2.7, 0., 1.) + u = solver.set_initial_condition() + + expected_array= [ + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.], + [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.], + [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + ] + + for x in range(u.shape[0]): + for y in range(u.shape[1]): +> assert expected_array[x][y] == u[x, y], f"Values at {x}, {y} do not match" +E AssertionError: Values at 0, 0 do not match +E assert 0.0 == np.float64(1.0) + +test_diffusion2d.py:46: AssertionError + + +============================== 1 failed in 0.21s =============================== + +Process finished with exit code 1 +``` ## Citing diff --git a/coverage-report.pdf b/coverage-report.pdf new file mode 100644 index 00000000..56e2b885 Binary files /dev/null and b/coverage-report.pdf differ diff --git a/diffusion2d.py b/diffusion2d.py index 51a07f2d..8d1c2b99 100644 --- a/diffusion2d.py +++ b/diffusion2d.py @@ -38,6 +38,11 @@ def __init__(self): self.dt = None def initialize_domain(self, w=10., h=10., dx=0.1, dy=0.1): + # You could argue individual assertions are better, since it allows to understand which values have the wrong type. + # However, for this exercise I keep it like this for initialize_domain and add individual assertions in initialize_physical_parameters + # In some cases individual assertions might not even allow for better understanding, if the assertion is deep in a library and the user might + # not understand how the values end up there. It probably is a case-by-case decision. + assert all(map(lambda v: type(v) == float, [w, h, dx, dy])), "All inputs must be floats" self.w = w self.h = h self.dx = dx @@ -45,7 +50,10 @@ def initialize_domain(self, w=10., h=10., dx=0.1, dy=0.1): self.nx = int(w / dx) self.ny = int(h / dy) - def initialize_physical_parameters(self, d=4., T_cold=300, T_hot=700): + def initialize_physical_parameters(self, d=4., T_cold=300., T_hot=700.): + assert type(d) == float, "d must be a float" + assert type(T_cold) == float, "T_cold must be a float" + assert type(T_hot) == float, "T_cold must be a float" self.D = d self.T_cold = T_cold self.T_hot = T_hot diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0a9352f0 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,5 @@ +# I had to add this file so pytest would actually find diffusion2d.py +[ pyproject.toml] + +[tool.pytest.ini_options] +pythonpath = "." diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..ac3f2889 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy>=1.15.0 +matplotlib>=3.0.0 \ No newline at end of file diff --git a/tests/integration/test_diffusion2d.py b/tests/integration/test_diffusion2d.py index fd026b40..a5bd1174 100644 --- a/tests/integration/test_diffusion2d.py +++ b/tests/integration/test_diffusion2d.py @@ -1,6 +1,7 @@ """ Tests for functionality checks in class SolveDiffusion2D """ +import pytest from diffusion2d import SolveDiffusion2D @@ -10,6 +11,12 @@ def test_initialize_physical_parameters(): Checks function SolveDiffusion2D.initialize_domain """ solver = SolveDiffusion2D() + solver.initialize_domain(10., 20., 0.2, 0.1) + solver.initialize_physical_parameters(2.4, 0., 1.) + # dx2 = 0.04 + # dy2 = 0.01 + # dt = 0.0004 / (2*2.4*0.05) = 1/600 = 0.0016666 + assert solver.dt == pytest.approx(0.001666, abs=1e-6) def test_set_initial_condition(): @@ -17,3 +24,23 @@ def test_set_initial_condition(): Checks function SolveDiffusion2D.get_initial_function """ solver = SolveDiffusion2D() + solver.initialize_domain(10., 10., 1., 1.) + solver.initialize_physical_parameters(2.7, 0., 1.) + u = solver.set_initial_condition() + + expected_array= [ + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.], + [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.], + [0., 0., 0., 0., 1., 1., 1., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], + ] + + for x in range(u.shape[0]): + for y in range(u.shape[1]): + assert expected_array[x][y] == u[x, y], f"Values at {x}, {y} do not match" diff --git a/tests/unit/pytest_test_diffusion2d_functions.py.bak b/tests/unit/pytest_test_diffusion2d_functions.py.bak new file mode 100644 index 00000000..3855e1fd --- /dev/null +++ b/tests/unit/pytest_test_diffusion2d_functions.py.bak @@ -0,0 +1,112 @@ +""" +Tests for functions in class SolveDiffusion2D +""" +import numpy as np +import pytest + +from diffusion2d import SolveDiffusion2D + + +def test_initialize_domain(): + """ + Check function SolveDiffusion2D.initialize_domain + """ + solver = SolveDiffusion2D() + # Arrange test values + w = 20. + h = 10. + dx = 2. + dy = 0.2 + + # Act (= Perform test action) + solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + assert solver.w == w + assert solver.h == h + assert solver.dx == dx + assert solver.dy == dy + # Calculated values + assert solver.nx == 10 + assert solver.ny == 50 + + +def test_initialize_domain_testcase_2(): + """ + Second testcase for function SolveDiffusion2D.initialize_domain + """ + solver = SolveDiffusion2D() + # Arrange test values + # "unschöne" values + w = 15.2 + h = 17.1 + dx = 2.7 + dy = 0.29 + + # Act (= Perform test action) + solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + assert solver.w == w + assert solver.h == h + assert solver.dx == dx + assert solver.dy == dy + # Calculated values + assert solver.nx == 5 + assert solver.ny == 58 + + +def test_initialize_physical_parameters(): + """ + Checks function SolveDiffusion2D.initialize_domain + """ + solver = SolveDiffusion2D() + # Arrange + d = 3.5 + T_cold = 342.4 + T_hot = 723.15 + solver.dx = 0.1 + solver.dy = 0.2 + + # Act + solver.initialize_physical_parameters(d, T_cold, T_hot) + + # Assert + assert solver.D == d + assert solver.T_cold == T_cold + assert solver.T_hot == T_hot + assert solver.dt == pytest.approx(0.001142, abs=1e-6) + + +def test_set_initial_condition(): + """ + Checks function SolveDiffusion2D.get_initial_function + """ + solver = SolveDiffusion2D() + # Arrange + solver.nx = 100 + solver.ny = 50 + solver.dx = 0.1 + solver.dy = 0.2 + solver.T_cold = 100. + solver.T_hot = 600. + + # Act + u: np.ndarray = solver.set_initial_condition() + + # Assert + # Domain has expected dimensions + assert u.shape[0] == solver.nx + assert u.shape[1] == solver.ny + # Border is cold, center is hot + assert u[0][0] == 100. + assert u[99][0] == 100. + assert u[0][49] == 100. + assert u[99][49] == 100. + + assert u[49][24] == 600. + assert u[50][24] == 600. + assert u[49][25] == 600. + assert u[50][25] == 600. diff --git a/tests/unit/test_diffusion2d_functions.py b/tests/unit/test_diffusion2d_functions.py index c4277ffd..87251d76 100644 --- a/tests/unit/test_diffusion2d_functions.py +++ b/tests/unit/test_diffusion2d_functions.py @@ -1,26 +1,116 @@ """ Tests for functions in class SolveDiffusion2D """ +from unittest import TestCase + +import numpy as np +import unittest from diffusion2d import SolveDiffusion2D -def test_initialize_domain(): - """ - Check function SolveDiffusion2D.initialize_domain - """ - solver = SolveDiffusion2D() +class TestDiffusion2D(unittest.TestCase): + + def setUp(self): + self.solver = SolveDiffusion2D() + + def test_initialize_domain(self): + """ + Check function SolveDiffusion2D.initialize_domain + """ + # Arrange test values + w = 20. + h = 10. + dx = 2. + dy = 0.2 + + # Act (= Perform test action) + self.solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + self.assertEqual(self.solver.w, w) + self.assertEqual(self.solver.h, h) + self.assertEqual(self.solver.dx, dx) + self.assertEqual(self.solver.dy, dy) + # Calculated values + self.assertEqual(self.solver.nx, 10) + self.assertEqual(self.solver.ny, 50) + + def test_initialize_domain_testcase_2(self): + """ + Second testcase for function SolveDiffusion2D.initialize_domain + """ + # Arrange test values + # "unschöne" values + w = 15.2 + h = 17.1 + dx = 2.7 + dy = 0.29 + + # Act (= Perform test action) + self.solver.initialize_domain(w, h, dx, dy) + + # Assert + # "cheap" assertions + self.assertEqual(self.solver.w, w) + self.assertEqual(self.solver.h, h) + self.assertEqual(self.solver.dx, dx) + self.assertEqual(self.solver.dy, dy) + # Calculated values + self.assertEqual(self.solver.nx, 5) + self.assertEqual(self.solver.ny, 58) + + def test_initialize_physical_parameters(self): + """ + Checks function SolveDiffusion2D.initialize_domain + """ + # Arrange + d = 3.5 + T_cold = 342.4 + T_hot = 723.15 + self.solver.dx = 0.1 + self.solver.dy = 0.2 + + # Act + self.solver.initialize_physical_parameters(d, T_cold, T_hot) + + # Assert + self.assertEqual(self.solver.D, d) + self.assertEqual(self.solver.T_cold, T_cold) + self.assertEqual(self.solver.T_hot, T_hot) + # unittest assumes rounding here, so the last decimal differs from pytest. + self.assertAlmostEqual(self.solver.dt, 0.001143, 6) + + def test_set_initial_condition(self): + """ + Checks function SolveDiffusion2D.get_initial_function + """ + # Arrange + self.solver.nx = 100 + self.solver.ny = 50 + self.solver.dx = 0.1 + self.solver.dy = 0.2 + self.solver.T_cold = 100. + self.solver.T_hot = 600. + # Act + u: np.ndarray = self.solver.set_initial_condition() -def test_initialize_physical_parameters(): - """ - Checks function SolveDiffusion2D.initialize_domain - """ - solver = SolveDiffusion2D() + # Assert + # Domain has expected dimensions + self.assertEqual(u.shape[0], self.solver.nx) + self.assertEqual(u.shape[1], self.solver.ny) + # Border is cold, center is hot + self.assertEqual(u[0][0], 100.) + self.assertEqual(u[99][0], 100.) + self.assertEqual(u[0][49], 100.) + self.assertEqual(u[99][49], 100.) + self.assertEqual(u[49][24], 600.) + self.assertEqual(u[50][24], 600.) + self.assertEqual(u[49][25], 600.) + self.assertEqual(u[50][25], 600.) -def test_set_initial_condition(): - """ - Checks function SolveDiffusion2D.get_initial_function - """ - solver = SolveDiffusion2D() +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tox.toml b/tox.toml new file mode 100644 index 00000000..874a35bd --- /dev/null +++ b/tox.toml @@ -0,0 +1,12 @@ +requires = ["tox>=4"] +env_list = ["pytest", "unittest"] + +[env.pytest] +description = "Run pytest" +deps = ["pytest>=8", "-r requirements.txt"] +commands = [["pytest", "tests/integration/test_diffusion2d.py"]] + +[env.unittest] +description = "Run unittest" +deps = ["-r requirements.txt"] +commands = [["python3", "-m", "unittest", "tests/unit/test_diffusion2d_functions.py"]] \ No newline at end of file