You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »

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

Download fruit.f90 https://github.com/mortele/FRUIT/blob/master/src/fruit.f90 and put it into ./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 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 ./scr 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 routines.

!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 its 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.

#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.



  • No labels