Instructor Notes
This is a placeholder file. Please add content here.
What is a Unit Test
Instructor Note
Challenge 2 should be lead by the instructor and done as a class activity. Part 3 can be skipped if there is limited time.
Writing your first unit test
pFUnit basics
Instructor Note
The dot function should only be a wrapper around the intrinsic function dot_product to keep the example simple but incorporate compiling src and tests together:
FORTRAN
module matrix_ops
implicit none
contains
!> Returns the dot product (a.b) of the two inputted arrays a and b
integer function dot(a, b)
!> The two arrays to be dotted together
integer :: a(:), b(:)
dot = dot_product(a, b)
end function dot
end module matrix_ops
When writing the pFUnit version of the unit test for the dot product, begin from this standard Fortran version to highlight the benefits of pFUnit.
FORTRAN
program test_matrix_ops_dot
use matrix_ops, only : dot
implicit none
integer :: i
! Declare passed and failure message arrays to be set by a test subroutine(s)
logical :: passed(1)
character(len=200) :: failure_message(1)
! Define set of tests for dot
call test_dot_one_to_twenty(passed(1), failure_message(1))
if (all(passed)) then
write(*,*) "All tests passed!"
else
do i = 1, size(passed)
if (.not. passed(i)) then
write(*,*) "FAIL: ", trim(failure_message(i))
end if
end do
stop 1
end if
contains
!> Unit test subroutine for dot
subroutine test_dot_one_to_twenty(passed, failure_message)
!> A logical to track whether the test passed or not
logical, intent(out) :: passed
!> A failure message to be displayed if passed is false
character(len=200), intent(out) :: failure_message
integer :: a(10), b(10), expected_c, actual_c
! Define inputs and expected outputs for the scenario we want to test
a = [1,2,3,4,5,6,7,8,9,10]
b = [11,12,13,14,15,16,17,18,19,20]
expected_c = 935
actual_c = dot(a, b)
! Check that the actual value matches the expected value
passed = expected_c == actual_c
! Populate the failure message
write(failure_message, '(A,I3,A,I3)') "Expected ", expected_c, " but got ", actual_c
end subroutine test_dot_one_to_twenty
end program test_matrix_ops_dot
This should be able to be compiled with the command
gfortran matrix_ops.f90 test_dot.f90
Instructor Note
To build and run this pFUnit version. Use the CMakeLists.txt below:
CMAKE
cmake_minimum_required(VERSION 3.9 FATAL_ERROR)
# Set project name
project(
"matrix_ops"
LANGUAGES "Fortran"
VERSION "0.0.1"
DESCRIPTION "Library for matrix operations"
)
# Define a variable which stores a list of src files
set(SRC_DIR "${PROJECT_SOURCE_DIR}")
set(PROJ_SRC_FILES "${SRC_DIR}/matrix_ops.f90")
#---------------------------
# Configure testing.
#---------------------------
enable_testing()
find_package(PFUNIT REQUIRED)
# Create library for src code
add_library(SUT STATIC ${PROJ_SRC_FILES})
# List all test files
set(test_srcs "${PROJECT_SOURCE_DIR}/test_dot.pf")
# Add the test target
add_pfunit_ctest (test_dot
TEST_SOURCES ${test_srcs}
LINK_LIBRARIES SUT # your application library
)
This can then be compiled with the following commands:
SH
cmake -B build -DCMAKE_PREFIX_PATH="/path/to/pfunit/build/installed"
cmake --build build
./build/test_dot
Integrating with build systems
Parameterising pFUnit tests
Instructor Note
The following challenge will take learners a long time to complete. Therefore, for shorter workshops, it is recommended to skip this and/or suggest it as some homework.
Testing parallel code
Instructor Note
When writing out the new MPI versions of the dot_product test, it is best to start from the serial version to emphasize the similarities between the two.