1. Example project structure
. ├── fruit │ └── fruit.f90 ├── mod ├── src │ └── <your_module>.f90 └── test ├── <your_module>_test.f90 └── <your_driver_name>.f90
- fruit.f90 - fruit source code
- mod - directory used to store .mod files
- <your_module>.f90 - your actual module
- <your_module>_test.f90 - file with unit tests for your module
- <your_driver_name>.f90 - file with test driving program. Filename could be anything, just remember it so you can use it while compiling and running project.
2. Install requirements
2.1. setup fruit library
Download fruit.f90 https://github.com/mortele/FRUIT/blob/master/src/fruit.f90 into .<project_dir>/fruit directory.
3. Create project files
3.1. Create file with unit tests
Create file named <your_module>_test.f90 and put it into ./test directory.
This is you file that contains unit tests for your program.
!file: <project_dir>/test/calculator_test.f90 module calculator_test use fruit contains subroutine test_calculator !use <your_module_name> use calculator integer :: result !test add subroutine call add (2,2,result) call assert_equals(4,result) end subroutine test_calculator end module calculator_test
3.2. Create unit test driver
Create file named <your_driver_name>.f90. It will call your tests and handle fruit init and summary.
!file: <project_dir>/test/fruit_driver.f90 program fruit_driver use fruit use calculator_test call init_fruit !if you want to generate XML result !call init_fruit_xml call test_calculator !call fruit_summary_xml call fruit_summary end program fruit_driver
3.3. Create your module
Create file named <your_module>.f90 and put it into ./src directory. This file will be tested by module created in step 3.1.
!file: <project_dir>/src/calculator.f90 module calculator implicit none contains subroutine add(a,b,output) integer, intent (in) :: a,b integer, intent (out) :: output output=a+b end subroutine add end module calculator
4. Using setup and teardown subroutines
NOTE: This step is optional and is needed to be done only if you want to use setup and teardown subroutines.
4.1. Add setup and teardown subroutines
First you need to define setup and teardown subroutines.
!file: <project_dir>/test/calculator_test.f90 module calculator_test use fruit contains subroutine setup !... end subroutine setup subroutine teardown !... end subroutine teardown subroutine test_calculator use calculator integer :: result !test add subroutine call add (2,2,result) call assert_equals(4,result) end subroutine test_calculator end module calculator_test
4.2. Create basket file
Basket file handles setup and teardown subroutines calls and also captures responsibility of running tests from test_driver module. It should be created in ./test directory.
!file: <project_dir>/test/fruit_basket.f90 module fruit_basket use fruit contains subroutine calculator_test_all_tests use calculator_test call setup write (*, *) " ..running test: test_calculator" call set_unit_name('test_calculator') call run_test_case (test_calculator, "test_calculator") if (.not. is_case_passed()) then write(*,*) write(*,*) ' Un-satisfied spec:' write(*,*) ' -- calculator' write(*,*) call case_failed_xml("test_calculator", & & "calculator_test") else call case_passed_xml("test_calculator", & & "calculator_test") end if call teardown end subroutine calculator_test_all_tests subroutine fruit_basket call calculator_test_all_tests end subroutine fruit_basket end module fruit_basket
Pay attention to code lines presented below. They come from code above. You can use them to call tests from desired test module.
call set_unit_name('test_calculator') call run_test_case (test_calculator, "test_calculator")
4.3. Modify test driver
Now test subroutines calls are moved from test_driver to test_basket. You need to import test_basket module and call it's main subroutine. In this case it is "fruit_basket" subroutine.
!file: <project_dir>/test/fruit_driver.f90 program fruit_driver use fruit use fruit_basket call init_fruit call fruit_basket call fruit_summary end program fruit_driver
5. Run tests
This bash code will compile all source codes and run tests described in ./test/calculator_test.f90 file. Just put it into .sh file and run.
#filename: build_run_and_clean.sh #create mod directory if not exists mkdir -p mod #compile source files # -J specifies where .mod files will be generated, and add this path in compiler search location gfortran -c ./src/*.f90 -J ./mod gfortran -c ./fruit/*.f90 -J ./mod gfortran -c ./test/*.f90 -J ./mod # create executable file gfortran -o fruit_driver *.o #run tests ./fruit_driver #clean find . -name "*.o" -type f -delete find . -name "*.mod" -type f -delete
6. Example output
6.1. Output created with project described above
6.2. Output created with different project
NOTE: FRUIT prints "." for every assert passed and "F" for every assert failed, not for every procedure call.
NOTE: Screenshoot below contains list of failed assertions and messages defined by user as optional assert subroutine argument.