Skip to content

Commit dbf6e83

Browse files
committed
More concise testing with tuff
1 parent 00acae2 commit dbf6e83

File tree

2 files changed

+91
-51
lines changed

2 files changed

+91
-51
lines changed

test/test_dense_layer.f90

Lines changed: 17 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,24 @@
11
program test_dense_layer
22
use iso_fortran_env, only: stderr => error_unit
3-
use nf, only: dense, layer
4-
use nf_activation, only: relu
3+
use nf, only: dense, layer, relu
4+
use tuff, only: test, test_result
55
implicit none
6-
type(layer) :: layer1, layer2
7-
logical :: ok = .true.
6+
type(layer) :: layer1, layer2, layer3
7+
type(test_result) :: tests
88

99
layer1 = dense(10)
10-
11-
if (.not. layer1 % name == 'dense') then
12-
ok = .false.
13-
write(stderr, '(a)') 'dense layer has its name set correctly.. failed'
14-
end if
15-
16-
if (.not. all(layer1 % layer_shape == [10])) then
17-
ok = .false.
18-
write(stderr, '(a)') 'dense layer is created with requested size.. failed'
19-
end if
20-
21-
if (layer1 % initialized) then
22-
ok = .false.
23-
write(stderr, '(a)') 'dense layer should not be marked as initialized yet.. failed'
24-
end if
25-
26-
if (.not. layer1 % activation == 'sigmoid') then
27-
ok = .false.
28-
write(stderr, '(a)') 'dense layer is defaults to sigmoid activation.. failed'
29-
end if
30-
31-
layer1 = dense(10, activation=relu())
32-
33-
if (.not. layer1 % activation == 'relu') then
34-
ok = .false.
35-
write(stderr, '(a)') 'dense layer is created with the specified activation.. failed'
36-
end if
37-
38-
layer2 = dense(20)
39-
call layer2 % init(layer1)
40-
41-
if (.not. layer2 % initialized) then
42-
ok = .false.
43-
write(stderr, '(a)') 'dense layer should now be marked as initialized.. failed'
44-
end if
45-
46-
if (.not. all(layer2 % input_layer_shape == [10])) then
47-
ok = .false.
48-
write(stderr, '(a)') 'dense layer should have a correct input layer shape.. failed'
49-
end if
50-
51-
if (ok) then
52-
print '(a)', 'test_dense_layer: All tests passed.'
53-
else
54-
write(stderr, '(a)') 'test_dense_layer: One or more tests failed.'
55-
stop 1
56-
end if
10+
layer2 = dense(10, activation=relu())
11+
layer3 = dense(20)
12+
call layer3 % init(layer1)
13+
14+
tests = test("Dense layer", [ &
15+
test("layer name is set", layer1 % name == 'dense'), &
16+
test("layer shape is correct", all(layer1 % layer_shape == [10])), &
17+
test("layer is initialized", layer3 % initialized), &
18+
test("layer's default activation is sigmoid", layer1 % activation == 'sigmoid'), &
19+
test("user set activation works", layer2 % activation == 'relu'), &
20+
test("layer initialized after init", layer3 % initialized), &
21+
test("layer input shape is set after init", all(layer3 % input_layer_shape == [10])) &
22+
])
5723

5824
end program test_dense_layer

test/tuff.f90

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
module tuff
2+
! Testing Unframework for Fortran (TUFF)
3+
use iso_fortran_env, only: stderr => error_unit, stdout => output_unit
4+
implicit none
5+
6+
private
7+
public :: test, test_result
8+
9+
type :: test_result
10+
character(:), allocatable :: name
11+
logical :: ok = .true.
12+
real :: elapsed = 0.
13+
end type test_result
14+
15+
interface test
16+
module procedure test_logical
17+
module procedure test_func
18+
module procedure test_array
19+
end interface test
20+
21+
abstract interface
22+
function func() result(res)
23+
import :: test_result
24+
type(test_result) :: res
25+
end function func
26+
end interface
27+
28+
contains
29+
30+
type(test_result) function test_logical(name, cond) result(res)
31+
! Test a single logical expression.
32+
character(*), intent(in) :: name
33+
logical, intent(in) :: cond
34+
res % name = name
35+
res % ok = .true.
36+
res % elapsed = 0.
37+
if (.not. cond) then
38+
write(stderr, '(a)') 'Test ' // trim(name) // ' failed.'
39+
res % ok = .false.
40+
end if
41+
end function test_logical
42+
43+
44+
type(test_result) function test_func(f) result(res)
45+
! Test a user-provided function f that returns a test_result.
46+
! f is responsible for setting the test name and the ok field.
47+
procedure(func) :: f
48+
real :: t1, t2
49+
res % name = ''
50+
call cpu_time(t1)
51+
res = f()
52+
call cpu_time(t2)
53+
res % elapsed = t2 - t1
54+
if (len_trim(res % name) == 0) res % name = 'Anonymous test'
55+
if (.not. res % ok) then
56+
write(stderr, '(a, f6.3)') 'Test failed: ' // trim(res % name)
57+
end if
58+
end function test_func
59+
60+
61+
type(test_result) function test_array(name, tests) result(suite)
62+
! Test a suite of tests, each of which is a test_result.
63+
character(*), intent(in) :: name
64+
type(test_result), intent(in) :: tests(:)
65+
suite % ok = all(tests % ok)
66+
suite % elapsed = sum(tests % elapsed)
67+
if (.not. suite % ok) then
68+
! Report to stderr only on failure.
69+
write(stderr, '(i0,a,i0,a)') count(.not. tests % ok), '/', size(tests), &
70+
" tests failed in suite: " // trim(name)
71+
end if
72+
end function test_array
73+
74+
end module tuff

0 commit comments

Comments
 (0)