Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/thomasms/toast
Testing Or ASsertion Toolkit - Fortran unit testing library
https://github.com/thomasms/toast
fortran fruit pfunit testcase testing toast unit-testing
Last synced: about 1 month ago
JSON representation
Testing Or ASsertion Toolkit - Fortran unit testing library
- Host: GitHub
- URL: https://github.com/thomasms/toast
- Owner: thomasms
- License: bsd-3-clause
- Created: 2018-04-23T20:54:09.000Z (almost 7 years ago)
- Default Branch: master
- Last Pushed: 2021-03-22T19:51:42.000Z (almost 4 years ago)
- Last Synced: 2024-12-02T09:06:17.850Z (about 2 months ago)
- Topics: fortran, fruit, pfunit, testcase, testing, toast, unit-testing
- Language: Fortran
- Homepage:
- Size: 63.5 KB
- Stars: 7
- Watchers: 3
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## TOAST -Testing Or ASsertion Toolkit
[![Build Status](https://travis-ci.org/thomasms/toast.svg?branch=master)](https://travis-ci.org/thomasms/toast)
A much needed library for Fortran.
Yes I know that pFUnit and FRUIT exist however:
- pFUnit maybe great but it is too complex and messy to use
- FRUIT is much simpler but a bit limited and not maintainedHence the need for Toast!
### Status:
Still very early, API likely to change.
- [x] Basic Test type
- [x] Support Int, Real and logical assert
- [x] Support for comparing character arrays
- [ ] Support Complex assert
- [x] Tolerances (absolute + relative) for real
- [x] Setup CI
- [ ] Testing needs testing
- [ ] Support for derived data types
- [ ] Support for arrays
- [ ] Support for mpi
- [ ] Ensure threadsafety
- [x] JSON output
- [ ] File comparision
- [ ] Regression testing frameworkToast can be used in 2 main ways:
1. Using the base TestCase for assertions only and a summary. It's very simple to use but limited
2. Extend the base TestCase to implement the run subroutine and make use of TestSuites. This works similar to Python unit testing framework.A simple example of type 1 usage is given in the example below:
```fortran
program example
use toast !< testing library
implicit nonetype(TestCase) :: test
call test%assertequal(3_ki4, 5_ki4)
call test%assertequal(3_ki4, 3_ki4)call test%assertequal(3.0_kr8, 3.0_kr8)
call test%assertequal(3.0_kr16, 3.0_kr16)call test%assertequal(3.0_kr4, 3.1_kr4, abs_tol=0.099_kr4)
call test%assertequal(3.0_kr4, 3.1_kr4, abs_tol=0.1_kr4)
call printsummary(test)end program example
```This will output:
```bash
example1 - FAILURE
[Passed assertions: 16 / 19 ] ++++++++++++++++
[Failed assertions: 3 / 19 ] ---Failure @ 3 does not equal 5
Failure @ arrays should not match
Failure @ 3 should not equal 3.1 with low toleranceexample1 - FAILURE
[Passed assertions: 4 / 6 ] ++++
[Failed assertions: 2 / 6 ] --Failure @ False should not be true.
Failure @ Assert strings are not equal1
```A simple example of type 2 usage is given in the example below:
```fortran
!> Define tests here
module exampletestcases
use toast !< testing library
implicit none
private!> We define the test case here
type, extends(TestCase), public :: PassingTestCaseExample
contains
procedure :: test => PassingTestCaseExampleProc
end type PassingTestCaseExample!> Alternatively, we can define a test case using the include macro
#define MACRO_TESTCASE_NAME FailingTestCaseExample
#define MACRO_TESTCASE_NAME_PROC FailingTestCaseExampleProc
#include "definetestcase.h"#define MACRO_TESTCASE_NAME PassAgainTestCaseExample
#define MACRO_TESTCASE_NAME_PROC PassAgainTestCaseExampleProc
#include "definetestcase.h"#define MACRO_TESTCASE_NAME FailAgainTestCaseExample
#define MACRO_TESTCASE_NAME_PROC FailAgainTestCaseExampleProc
#include "definetestcase.h"contains
!> passing test example
subroutine PassingTestCaseExampleProc(this)
class(PassingTestCaseExample), intent(inout) :: this! integer asserts
call this%assertequal(127_ki1, 127_ki1, message = "127 should equal 127")
call this%assertequal(32767_ki2, 32767_ki2, message = "32767 should equal 32767")
call this%assertequal(3.0_kr8, 3.0_kr8, message = "3 should equal 3")
call this%assertequal(3.0_kr4, 3.1_kr4, abs_tol=0.1_kr4, &
& message = "3 should equal 3.1 with higher tolerance")
call this%asserttrue(2_ki4*3_ki4 == 6_ki4, "2*3 == 6 should be true.")
call this%assertfalse(.false., "False should be false.")end subroutine
!> failing test example
subroutine FailingTestCaseExampleProc(this)
class(FailingTestCaseExample), intent(inout) :: this! integer asserts
call this%assertequal(127_ki1, 12_ki1, message = "127 should equal 127")
call this%assertequal(32767_ki2, 327_ki2, message = "32767 should equal 32767")
call this%assertequal(3.0_kr8, 3.4_kr8, message = "3 should equal 3")
call this%assertequal(3.0_kr4, 3.1_kr4, abs_tol=0.09_kr4, &
& message = "3 should equal 3.1 with higher tolerance")
call this%asserttrue(2_ki4*3_ki4 == 7_ki4, "2*3 == 6 should be true.")
call this%assertfalse(.true., "False should be false.")end subroutine
!> passing test example
subroutine PassAgainTestCaseExampleProc(this)
class(PassAgainTestCaseExample), intent(inout) :: thiscall this%asserttrue(.not. .false., "Not false should be true.")
end subroutine
!> failing test example
subroutine FailAgainTestCaseExampleProc(this)
class(FailAgainTestCaseExample), intent(inout) :: thiscall this%asserttrue(.false., "false cannot be true.")
end subroutine
end module exampletestcases
!> Main test program
program example
use toast
use exampletestcases
implicit nonetype(TestSuite) :: suite
suite = TestSuite(name="My test suite")! add the tests here
call suite%append(PassingTestCaseExample(name="passing_case1"))
call suite%append(FailingTestCaseExample(name="failing_case1"))
call suite%append(PassAgainTestCaseExample(name="passing_case2"))
call suite%append(FailAgainTestCaseExample(name="failing_case2"))
call suite%append(PassingTestCaseExample(name="passing_case1_again"))call suite%runall()
call printsummary(suite)end program example
```This will output:
```bash
[2136][tom@Unknown:~/Dev/toast/buildifort/bin]$ ./toastexample2
-- test case results --
passing_case1 - SUCCESS
[Passed assertions: 6 / 6 ] ++++++
[Failed assertions: 0 / 6 ]failing_case1 - FAILURE
[Passed assertions: 0 / 6 ]
[Failed assertions: 6 / 6 ] ------Failure @ 127 should equal 127
Failure @ 32767 should equal 32767
Failure @ 3 should equal 3
Failure @ 3 should equal 3.1 with higher tolerance
Failure @ 2*3 == 6 should be true.
Failure @ False should be false.passing_case2 - SUCCESS
[Passed assertions: 3 / 3 ] +++
[Failed assertions: 0 / 3 ]failing_case2 - FAILURE
[Passed assertions: 0 / 2 ]
[Failed assertions: 2 / 2 ] --Failure @ false cannot be true.
Failure @ arrays should not matchpassing_case1_again - SUCCESS
[Passed assertions: 6 / 6 ] ++++++
[Failed assertions: 0 / 6 ]-------------------------------------
-- TOAST test results ---- FAILURE --
[Passed test cases: 3 / 5] ( 15 / 23 asserts)
[Failed test cases: 2 / 5] ( 8 / 23 asserts)
```Due to generic type bound procedures on the TestCase type, the compiler catches errors when trying to compare different types, for example, the following will not compile:
```fortran
program example
use toast !< testing library
implicit none
type(TestCase) :: test!> Will not compile since kr16 and kr4 are different types
call test%assertequal(3.0_kr16, 3.0_kr4)
call printsummary(test)end program example
```