You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Several key aspects define a unit test. They should be...
28
+
Several key aspects define a unit test. They should be…
30
29
31
30
-**Isolated** - Does not rely on any other unit of code within the repository.
32
31
-**Minimal** - Tests only one unit of code.
33
-
-**Fast** - Run on the scale of ms or s.
32
+
-**Fast** - Run on the scale of ms or s.
34
33
35
34
::::::::::::::::::::::::::::::::::::: callout
36
35
37
36
### Other forms of testing
38
37
39
-
There are other forms of testing, such as integration testing in which two or more units of a code base are tested to verify that they work together, or that they are correctly **integrated**.
40
-
However, today we are focusing on unit tests as it is often the case that many of these larger tests are written using the same test tools and frameworks, hence we will make progress with both by starting with unit testing.
38
+
There are other forms of testing, such as integration testing in which two or more units of a code base are tested to verify that
39
+
they work together, or that they are correctly **integrated**. However, today we are focusing on unit tests as it is often the
40
+
case that many of these larger tests are written using the same test tools and frameworks, hence we will make progress with both by
41
+
starting with unit testing.
41
42
42
43
::::::::::::::::::::::::::::::::::::::::::::::::
43
44
@@ -46,24 +47,29 @@ However, today we are focusing on unit tests as it is often the case that many o
46
47
All unit tests tend to follow the same pattern of Given-When-Then.
47
48
48
49
-**Given** we are in some specific starting state
49
-
- Units of code almost always have some inputs. These inputs may be scalars to be passed into a function, but they may also be an external dependency such as a database, file or array which must be allocated.
50
-
- This database, file or array memory must exist before the unit can be tested. Hence, we must set up this state in advance of calling the unit we are testing.
50
+
- Units of code almost always have some inputs. These inputs may be scalars to be passed into a function, but they may also be
51
+
an external dependency such as a database, file or array which must be allocated.
52
+
- This database, file or array memory must exist before the unit can be tested. Hence, we must set up this state in advance of
53
+
calling the unit we are testing.
51
54
-**When** we carry out a specific action
52
-
- This is the step in which we call the unit of code to be tested, such as a call to a function or subroutine.
53
-
- We should limit the number of actions being performed here to ensure it is easy to determine which unit is failing in the event that a test fails.
55
+
- This is the step in which we call the unit of code to be tested, such as a call to a function or subroutine.
56
+
- We should limit the number of actions being performed here to ensure it is easy to determine which unit is failing in the event
57
+
that a test fails.
54
58
-**Then** some specific event/outcome will have occurred.
55
-
- Once we have called our unit of code, we must check that what we expected to happen did indeed happen.
56
-
- This could mean comparing a scalar or vector quantity returned from the called unit against some expected value. However, it could be something more complex such as validating the contents of a database or outputted file.
59
+
- Once we have called our unit of code, we must check that what we expected to happen did indeed happen.
60
+
- This could mean comparing a scalar or vector quantity returned from the called unit against some expected value. However, it
61
+
could be something more complex such as validating the contents of a database or outputted file.
62
+
63
+
::::::::::::::::::::::::::::::::::::: challenge
57
64
58
-
::::::::::::::::::::::::::::::::::::: challenge
65
+
### Challenge 1: Write a unit test in pseudo code
59
66
60
-
### Challenge 1: Write a unit test in pseudo code.
67
+
Assuming you have a function `reverse_array` which reverses the order of an allocated array. Write a unit test in pseudo code for
68
+
`reverse_array` using the pattern above.
61
69
62
-
Assuming you have a function `reverse_array` which reverses the order of an allocated array. Write a unit test in pseudo code for `reverse_array` using the pattern above.
70
+
:::::::::::::::::::::::: solution
63
71
64
-
:::::::::::::::::::::::: solution
65
-
66
-
```
72
+
```txt
67
73
! Given
68
74
Allocate the input array `input_array`
69
75
Fill `input_array`, for example with `(1,2,3,4)`
@@ -83,7 +89,9 @@ for each element in `input_array`:
83
89
84
90
## When should unit tests be run?
85
91
86
-
A major benefit of unit tests is the ability to identify bugs at the earliest possible stage. Therefore, unit tests should be run frequently throughout the development process. Passing unit tests give you and your collaborators confidence that changes to your code aren't modifying the previously expected behaviour, so run your unit tests...
92
+
A major benefit of unit tests is the ability to identify bugs at the earliest possible stage. Therefore, unit tests should be run
93
+
frequently throughout the development process. Passing unit tests give you and your collaborators confidence that changes to your
94
+
code aren't modifying the previously expected behaviour, so run your unit tests…
87
95
88
96
- if you make a change locally
89
97
- if you raise a merge request
@@ -96,37 +104,47 @@ Basically, all the time.
96
104
97
105
## Do we really need unit tests?
98
106
99
-
Yes!
107
+
Yes!
100
108
101
-
You may be thinking that you don't require unit tests as you already have some well-defined end-to-end test cases which demonstrate that your code base works as expected. However, consider the case where this end-to-end test begins to fail. The message for this failure is likely to be something along the lines of
109
+
You may be thinking that you don't require unit tests as you already have some well-defined end-to-end test cases which
110
+
demonstrate that your code base works as expected. However, consider the case where this end-to-end test begins to fail. The
111
+
message for this failure is likely to be something along the lines of
102
112
103
-
```
113
+
```txt
104
114
Expected my_special_number to be 1.234 but got 5.678
105
115
```
106
116
107
-
If you have a comprehensive understanding of your code, perhaps this is all you need. However, assuming the newest feature that caused this failure was not written by you, it's going to be difficult to identify what is going wrong without some lengthy debugging.
117
+
If you have a comprehensive understanding of your code, perhaps this is all you need. However, assuming the newest feature that
118
+
caused this failure was not written by you, it's going to be difficult to identify what is going wrong without some lengthy debugging.
108
119
109
-
Now imagine the situation where this developer added unit tests for their new code. When running these unit tests, you may see something like
120
+
Now imagine the situation where this developer added unit tests for their new code. When running these unit tests, you may see
121
+
something like
110
122
111
-
```
123
+
```txt
112
124
test_populate_arrays Failed: Expected 1 for index 1 but got 0
113
125
```
114
126
115
-
This is much clearer. We immediately have an idea of what could be going wrong and the unit test itself will help us determine the problematic code to investigate.
127
+
This is much clearer. We immediately have an idea of what could be going wrong and the unit test itself will help us determine the
128
+
problematic code to investigate.
116
129
117
-
::::::::::::::::::::::::::::::::::::: challenge
130
+
::::::::::::::::::::::::::::::::::::: challenge
118
131
119
132
## Challenge 2: Unit test bad practices
120
133
121
-
Take a look at [1-into-to-unit-tests/challenge](https://github.com/carpentries-incubator/fortran-unit-testing/tree/main/exercises/1-into-to-unit-tests/challenge) in the exercises repository.
A solution is provided in [1-into-to-unit-tests/solution](https://github.com/carpentries-incubator/fortran-unit-testing/tree/main/exercises/1-into-to-unit-tests/solution).
- David Thomas and Andrew Hunt (2019). [The Pragmatic Programmer: your journey to mastery](https://search.worldcat.org/search?q=bn:9780135957059), 20th Anniversary Edition, 2nd Edition. Addison-Wesley Professional.
148
+
- David Thomas and Andrew Hunt (2019).
149
+
[The Pragmatic Programmer: your journey to mastery](https://search.worldcat.org/search?q=bn:9780135957059)
0 commit comments