Quickstart (using fpm)

Quickstart (using fpm)#

You will learn to

  • create a minimal project with the Fortran package manager (fpm),

  • add unit tests to the project,

  • build the project and run the tests.

Before jumping in#

To begin this quickstart tutorial on Fortuno, ensure to have a recent version of the Fortran package manager (fpm) (version 0.10 or newer) and a Fortran compiler that implements the Fortran 2018 standard. Fortuno operates smoothly with recent versions of several popular Fortran compilers, but older Fortran compilers are known to fail to build it. Please check the minimal compiler versions in the Fortuno readme.

Getting comfortable#

We’ll create a library named mylib containing a single function factorial() to calculate the factorial of an integer. The testing of the library shall be automated using unit tests.

We first create a new project for mylib using fpm:

fpm new mylib

Then, we add the following to the fpm.toml file (package manifest) to include Fortuno as a development dependency:

[dev-dependencies]
fortuno = { git = "https://github.com/fortuno-repos/fortuno-fpm-serial.git" }

We develop the first version of our library by adapting src/mylib.f90 as follows:

src/mylib.f90#
!> Demo library to be unit-tested.
module mylib
  implicit none

  private
  public :: factorial

contains

  !> Calculates the factorial of a number.
  function factorial(nn) result(fact)

    !> number to calculate the factorial of
    integer, intent(in) :: nn

    !> factorial (note, there is no check made for integer overflow!)
    integer :: fact

    integer :: ii

    fact = 1
    do ii = 2, nn
      fact = fact * ii
    end do

  end function factorial

end module mylib

The main executable of our project should just print out the factorial for three specific values, so that we can check whether our factorial() function works as expected:

app/main.f90#
program main
  use mylib, only: factorial
  implicit none

  print "('factorial(', i0, ') = ', i0)",&
      & 0, factorial(0),&
      & 1, factorial(1),&
      & 2, factorial(2)

end program main

Now, let’s automatize the testing procedure. We will write three unit tests, which check the factorial function for the specific input values 0, 1 and 2. The last test should intentionally fail to demonstrate the error reporting. Rename the file test/check.f90 into test/testapp.f90 and modify the content as follows:

test/testapp.f90#
!> Fortuno unit tests
module test_mylib
  use mylib, only : factorial
  use fortuno_serial, only : is_equal, test => serial_case_item, check => serial_check, test_list
  implicit none

contains

  function tests()
    type(test_list) :: tests

    tests = test_list([&
        test("factorial_0", test_factorial_0),&
        test("factorial_1", test_factorial_1),&
        test("factorial_2", test_factorial_2)&
    ])

  end function tests

  ! Test: 0! = 1
  subroutine test_factorial_0()
    call check(factorial(0) == 1)
  end subroutine test_factorial_0

  ! Test: 1! = 1
  subroutine test_factorial_1()
    call check(is_equal(factorial(1), 1))
  end subroutine test_factorial_1

  ! Test: 2! = 3 (will fail to demonstrate the output of a failing test)
  subroutine test_factorial_2()
    ! Failing check, you should obtain detailed info about the failure.
    call check(&
        & is_equal(factorial(2), 3),&
        & msg="Test failed for demonstration purposes"&
    )
  end subroutine test_factorial_2

end module test_mylib


!> Test app driving Fortuno unit tests.
program testapp
  use test_mylib, only : tests
  use fortuno_serial, only : execute_serial_cmd_app
  implicit none

  call execute_serial_cmd_app(tests())

end program testapp

Let’s build our library and run the units tests by issuing

fpm test

in the main project folder. The expected output will show two successful tests and one failure, providing detailed information on the failed test.

Output of the “fpm test” command#
=== Fortuno - flextensible unit testing framework for Fortran ===

# Executing test items
..F

# Logged event(s)

Failed     [run] factorial_2

-> Unsuccessful check
Check: 1
Msg: Test failed for demonstration purposes
Failure: mismatching integer values
Value1: 2
Value2: 3


# Test runs
Total:      3
Succeeded:  2  ( 66.7%)
Failed:     1  ( 33.3%)

=== FAILED ===

Congratulations! You’ve now implemented and completed your first set of Fortuno unit tests, assessing your project’s integrity.

See also

  • Section Key concepts contains a detailed analyzis of this minimal test application and also more information on some key concepts.