Skip to content

Commit 2d74bc1

Browse files
authored
Merge pull request #32 from UCL-ARC/27-add-first-unit-test-ep
2 parents 147f6b0 + 48c44aa commit 2d74bc1

File tree

72 files changed

+562
-28
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+562
-28
lines changed

.github/workflows/test.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,6 @@ jobs:
4747

4848
- name: Test episode 5
4949
run: docker build . -f docker/Dockerfile.ep-5
50+
51+
- name: Test episode 6
52+
run: docker build . -f docker/Dockerfile.ep-6

docker/Dockerfile.ep-3

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
FROM ghcr.io/ucl-arc/fortran-unit-testing-exercises:main
22

3-
COPY --chown=vscode episodes/3-fortran-unit-test-syntax /home/vscode/3-fortran-unit-test-syntax
3+
COPY --chown=vscode episodes/3-writing-your-first-unit-test /home/vscode/3-writing-your-first-unit-test
44

5-
WORKDIR /home/vscode/3-fortran-unit-test-syntax/solution
5+
# Test the Challenge code
66

7-
# build tests with cmake
8-
RUN cmake -B build -DCMAKE_PREFIX_PATH=/home/vscode/pfunit/build/installed && \
9-
cmake --build build
7+
WORKDIR /home/vscode/3-writing-your-first-unit-test/challenge
108

11-
# test pfunit with ctest
12-
RUN ctest --test-dir build --output-on-failure
9+
# Rebuild without pFUnit
10+
RUN cmake -B build-std && \
11+
cmake --build build-std
12+
13+
# Test without pFUnit
14+
RUN ctest --test-dir build-std --output-on-failure
1315

16+
17+
# Test the Solution code
18+
19+
# Cleanup directories
20+
RUN rm -rf build-std build-pf
21+
22+
# Copy solution code
23+
RUN cp ../solution/test_temp_conversions.f90 test/standard_fortran/ && \
24+
cp ../solution/test_temp_conversions.pf test/pfunit/
25+
26+
RUN ls test/pfunit/
27+
28+
# Rebuild without pFUnit
29+
RUN cmake -B build-std && \
30+
cmake --build build-std
31+
32+
# Rebuild with pFUnit
33+
RUN cmake -B build-pf -DCMAKE_PREFIX_PATH=/home/vscode/pfunit/build/installed && \
34+
cmake --build build-pf
35+
36+
# Test without pFUnit
37+
RUN ctest --test-dir build-std --output-on-failure
38+
39+
# Test with pFUnit
40+
RUN ctest --test-dir build-pf --output-on-failure

docker/Dockerfile.ep-4

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
FROM ghcr.io/ucl-arc/fortran-unit-testing-exercises:main
22

3-
COPY --chown=vscode episodes/4-debugging-a-broken-test /home/vscode/4-debugging-a-broken-test
3+
COPY --chown=vscode episodes/4-fortran-unit-test-syntax /home/vscode/4-fortran-unit-test-syntax
44

5-
WORKDIR /home/vscode/4-debugging-a-broken-test/challenge
6-
7-
# Fix intentional bug in code
8-
RUN sed -i -E 's/.*matrix\(row, col\) = temp_matrix\(row, col\)/matrix\(col, row\) = temp_matrix\(row, col\)/g' src/matrix_transforms.f90
5+
WORKDIR /home/vscode/4-fortran-unit-test-syntax/solution
96

107
# build tests with cmake
118
RUN cmake -B build -DCMAKE_PREFIX_PATH=/home/vscode/pfunit/build/installed && \
129
cmake --build build
1310

1411
# test pfunit with ctest
1512
RUN ctest --test-dir build --output-on-failure
13+

docker/Dockerfile.ep-5

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,15 @@
11
FROM ghcr.io/ucl-arc/fortran-unit-testing-exercises:main
22

3-
COPY --chown=vscode episodes/5-testing-parallel-code /home/vscode/5-testing-parallel-code
3+
COPY --chown=vscode episodes/5-debugging-a-broken-test /home/vscode/5-debugging-a-broken-test
44

5-
WORKDIR /home/vscode/5-testing-parallel-code/challenge
5+
WORKDIR /home/vscode/5-debugging-a-broken-test/challenge
66

77
# Fix intentional bug in code
8-
RUN mv ../solution/test_find_steady_state.pf ./test/ && \
9-
echo "set(test_find_steady_state_src \${test_srcs})\n\
10-
list(FILTER test_find_steady_state_src INCLUDE REGEX \".*test_find_steady_state.pf\")\n\
11-
\n\
12-
add_pfunit_ctest (pfunit_find_steady_state_tests\n\
13-
TEST_SOURCES \${test_find_steady_state_src}\n\
14-
LINK_LIBRARIES sut\n\
15-
MAX_PES 8\n\
16-
)\n\
17-
" >> test/CMakeLists.txt
8+
RUN sed -i -E 's/.*matrix\(row, col\) = temp_matrix\(row, col\)/matrix\(col, row\) = temp_matrix\(row, col\)/g' src/matrix_transforms.f90
189

1910
# build tests with cmake
20-
RUN cmake -B build-cmake -DCMAKE_PREFIX_PATH=/home/vscode/pfunit/build/installed && \
21-
cmake --build build-cmake
11+
RUN cmake -B build -DCMAKE_PREFIX_PATH=/home/vscode/pfunit/build/installed && \
12+
cmake --build build
2213

23-
# test with ctest, allowing MPI to oversubscribe
24-
RUN ctest --test-dir build-cmake --output-on-failure
14+
# test pfunit with ctest
15+
RUN ctest --test-dir build --output-on-failure

docker/Dockerfile.ep-6

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM ghcr.io/ucl-arc/fortran-unit-testing-exercises:main
2+
3+
COPY --chown=vscode episodes/6-testing-parallel-code /home/vscode/6-testing-parallel-code
4+
5+
WORKDIR /home/vscode/6-testing-parallel-code/challenge
6+
7+
# Fix intentional bug in code
8+
RUN mv ../solution/test_find_steady_state.pf ./test/ && \
9+
echo "set(test_find_steady_state_src \${test_srcs})\n\
10+
list(FILTER test_find_steady_state_src INCLUDE REGEX \".*test_find_steady_state.pf\")\n\
11+
\n\
12+
add_pfunit_ctest (pfunit_find_steady_state_tests\n\
13+
TEST_SOURCES \${test_find_steady_state_src}\n\
14+
LINK_LIBRARIES sut\n\
15+
MAX_PES 8\n\
16+
)\n\
17+
" >> test/CMakeLists.txt
18+
19+
# build tests with cmake
20+
RUN cmake -B build-cmake -DCMAKE_PREFIX_PATH=/home/vscode/pfunit/build/installed && \
21+
cmake --build build-cmake
22+
23+
# test with ctest, allowing MPI to oversubscribe
24+
RUN ctest --test-dir build-cmake --output-on-failure
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
2+
3+
# Set project name
4+
project(
5+
"temp_conversions"
6+
LANGUAGES "Fortran"
7+
VERSION "0.0.1"
8+
DESCRIPTION "Library for converting between various temperatures"
9+
)
10+
11+
# Define src file(s)
12+
set(PROJ_SRC_FILES "${PROJECT_SOURCE_DIR}/src/temp_conversions.f90")
13+
14+
enable_testing()
15+
add_subdirectory("test")
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Writing your first unit test - Standard Fortran
2+
3+
This exercise aims to teach the principles of unit testing and how to write a good
4+
unit test. The tests within this challenge are intended to be written using standard
5+
Fortran without the use of a testing framework, in order to teach the principles alone.
6+
7+
## The src code
8+
9+
In [src](./src) you will find a library [temp_conversions.f90](./src/temp_conversions.f90)
10+
which provides functions for converting between various units of temperature. The functions
11+
provided are...
12+
13+
- **fahrenheit_to_celsius**: Which takes in a temperature in Fahrenheit and returns a temperature in Celsius.
14+
- **celsius_to_kelvin**: Which takes in a temperature in Celsius and returns a temperature in Kelvin.
15+
16+
## The tasks
17+
18+
### Part 1 - Test with Standard Fortran
19+
20+
Imagine you wish to use the temp_conversions library to convert Fahrenheit to Kelvin. We
21+
know that there is no function which does this direct conversion. With this is mind, write
22+
a test, or tests, to give you confidence that temp_conversions can correctly convert
23+
Fahrenheit to Kelvin.
24+
25+
To get you started, the file [test_temp_conversions.f90](./test/standard_fortran/test_temp_conversions.f90)
26+
has been provided. `test_temp_conversions.f90` contains some boilerplate to make writing a
27+
test easier. There is an empty test subroutine `test` provided which takes in a logical
28+
`passed` and a character array `failure_message`. The logical `passed` should indicate if
29+
the test was successful. The character array `failure_message`, should be populated with a
30+
message that will be printed to the terminal in the event that `passed` is `.false.`. Once
31+
the test subroutine is written it should be called within the main body of the test program
32+
as indicated in `test_temp_conversions.f90`.
33+
34+
> Not: If you add a new test file or change the name of `test_temp_conversions.f90`, you will
35+
> need to update list of tests (`test_src`) in [test/pfunit/CMakeLists.txt](./test/pfunit/CMakeLists.txt)
36+
37+
### Part 2 - Convert tests to use pFUnit
38+
39+
Convert your tests from [Part 1](#part-1---test-with-standard-fortran), to use
40+
[pFUnit](https://github.com/Goddard-Fortran-Ecosystem/pFUnit).
41+
42+
A file [test_temp_conversions.pf](./test/pfunit/test_temp_conversions.pf) containing a template
43+
for your pFUnit test(s) has been provided. Comments within this file indicate the aspects of
44+
the pFUnit test you must write.
45+
46+
> Note: This template has been written to facilitate conversion of
47+
> [test_temp_conversions.f90](./test/standard_fortran/test_temp_conversions.f90) as provided with this repo
48+
> to pFUnit. If your version of test_temp_conversions.f90, produced in Part 1, is significantly
49+
> different, You may prefer to use a different structure to the one provided in the template.
50+
51+
To build and run your pFUnit test(s) you must add the pFUnit lib to the `CMAKE_PREFIX_PATH`
52+
when building via the following command.
53+
54+
```bash
55+
cmake -B build -DCMAKE_PREFIX_PATH=/path/to/pfunit/install
56+
cmake --build build
57+
ctest --test-dir build --output-on-failure
58+
```
59+
60+
If your test does not get built, ensure you have added it to the list of tests (`test_src`)
61+
in [test/pfunit/CMakeLists.txt](./test/pfunit/CMakeLists.txt)
62+
63+
> If you are using the devcontainer, there is an installation of pFUnit at /home/vscode/pfunit/build/installed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module temp_conversions
2+
implicit none
3+
private
4+
public :: fahrenheit_to_celsius, celsius_to_kelvin
5+
6+
contains
7+
8+
function fahrenheit_to_celsius(fahrenheit) result(celsius)
9+
real, intent(in) :: fahrenheit
10+
real :: celsius
11+
celsius = (fahrenheit - 32.0) * 5.0 / 9.0
12+
end function fahrenheit_to_celsius
13+
14+
function celsius_to_kelvin(celsius) result(kelvin)
15+
real, intent(in) :: celsius
16+
real :: kelvin
17+
kelvin = celsius + 273.15
18+
end function celsius_to_kelvin
19+
20+
end module temp_conversions
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
find_package(PFUNIT QUIET)
2+
3+
add_subdirectory("standard_fortran")
4+
5+
if (PFUNIT_FOUND)
6+
add_subdirectory("pfunit")
7+
endif()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*.f90
2+
*.F90

0 commit comments

Comments
 (0)