Skip to content

Commit 007de65

Browse files
authored
Merge pull request #149 from BerkeleyLab/selective-test-execution
Test reordering and selective test execution
2 parents 0f99b40 + 4fa5165 commit 007de65

9 files changed

+288
-161
lines changed

fpm.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name = "inference-engine"
2-
version = "0.11.0"
2+
version = "0.11.1"
33
license = "see LICENSE.txt"
44
author = "Damian Rouson, Tan Nguyen, Jordan Welsman, David Torres, Brad Richardson, Katherine Rasmussen, Federica Villani"
55
maintainer = "rouson@lbl.gov"
66

77
[dependencies]
88
assert = {git = "https://github.com/sourceryinstitute/assert", tag = "1.6.0"}
9-
sourcery = {git = "https://github.com/sourceryinstitute/sourcery", tag = "4.6.1"}
9+
sourcery = {git = "https://github.com/sourceryinstitute/sourcery", tag = "4.8.0"}

test/asymmetric_engine_test_m.F90

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ module asymmetric_engine_test_m
55

66
! External dependencies
77
use assert_m, only : assert
8-
use sourcery_m, only : string_t, test_t, test_result_t
8+
use sourcery_m, only : &
9+
test_t, test_result_t, vector_test_description_t, test_description_substring, string_t, vector_function_strategy_t
910

1011
! Internal dependencies
1112
use inference_engine_m, only : inference_engine_t, tensor_t
@@ -22,6 +23,11 @@ module asymmetric_engine_test_m
2223
procedure, nopass :: results
2324
end type
2425

26+
type, extends(vector_function_strategy_t) :: xor_and_2nd_input_t
27+
contains
28+
procedure, nopass :: vector_function => xor_and_2nd_input_truth_table
29+
end type
30+
2531
contains
2632

2733
pure function subject() result(specimen)
@@ -31,34 +37,28 @@ pure function subject() result(specimen)
3137

3238
function results() result(test_results)
3339
type(test_result_t), allocatable :: test_results(:)
34-
35-
character(len=*), parameter :: longest_description = &
36-
"mapping (false,false) to false"
37-
#ifdef _CRAYFTN
38-
character(len=len(longest_description)), allocatable :: descriptions(:)
39-
logical, allocatable :: outcomes(:)
40-
descriptions = [ "mapping (true,true) to false", "mapping (true,false) to false", &
41-
"mapping (false,true) to true", "mapping (false,false) to false" ]
42-
outcomes = xor_and_2nd_input_truth_table()
43-
#else
44-
associate( &
45-
descriptions => &
46-
[ character(len=len(longest_description)) :: &
47-
"mapping (true,true) to false", &
48-
"mapping (true,false) to false", &
49-
"mapping (false,true) to true", &
50-
"mapping (false,false) to false" &
51-
], &
52-
outcomes => &
53-
[ xor_and_2nd_input_truth_table() &
54-
] &
40+
type(xor_and_2nd_input_t) xor_and_2nd_input
41+
42+
associate( vector_test_description => vector_test_description_t( &
43+
[ string_t("mapping (true,true) to false"), &
44+
string_t("mapping (true,false) to false"), &
45+
string_t("mapping (false,true) to true"), &
46+
string_t("mapping (false,false) to false") &
47+
], xor_and_2nd_input) &
5548
)
56-
#endif
57-
call assert(size(descriptions) == size(outcomes),"asymetric_engine_test_m(results): size(descriptions) == size(outcomes)")
58-
test_results = test_result_t(descriptions, outcomes)
59-
#ifndef _CRAYFTN
49+
associate(substring_in_subject => index(subject(), test_description_substring) /= 0)
50+
associate(substring_in_description => vector_test_description%contains_text(test_description_substring))
51+
if (substring_in_subject) then
52+
test_results = vector_test_description%run()
53+
else if (any(substring_in_description)) then
54+
test_results = vector_test_description%run()
55+
test_results = pack(test_results, test_results%description_contains(string_t(test_description_substring)))
56+
else
57+
test_results = [test_result_t::]
58+
end if
59+
end associate
60+
end associate
6061
end associate
61-
#endif
6262
end function
6363

6464
function xor_and_2nd_input_network() result(inference_engine)

test/hyperparameters_test_m.F90

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ module hyperparameters_test_m
44
!! Test hyperparameters_t object I/O and construction
55

66
! External dependencies
7-
use assert_m, only : assert
8-
use sourcery_m, only : string_t, test_t, test_result_t, file_t
97
use inference_engine_m, only : hyperparameters_t
8+
use sourcery_m, only : test_t, test_result_t, test_description_t, test_description_substring, string_t
9+
#ifdef __GFORTRAN__
10+
use sourcery_m, only : test_function_i
11+
#endif
1012

1113
! Internal dependencies
1214
use hyperparameters_m, only : hyperparameters_t
@@ -30,24 +32,32 @@ pure function subject() result(specimen)
3032
end function
3133

3234
function results() result(test_results)
35+
type(test_description_t), allocatable :: test_descriptions(:)
3336
type(test_result_t), allocatable :: test_results(:)
3437

35-
character(len=*), parameter :: longest_description = &
36-
"component-wise construction followed by conversion to and from JSON"
38+
#ifndef __GFORTRAN__
39+
test_descriptions = [ &
40+
test_description_t( &
41+
string_t("component-wise construction followed by conversion to and from JSON"), &
42+
write_then_read_hyperparameters) &
43+
]
44+
#else
45+
procedure(test_function_i), pointer :: check_write_then_read_ptr
46+
check_write_then_read_ptr => write_then_read_hyperparameters
3747

48+
test_descriptions = [ &
49+
test_description_t( &
50+
string_t("component-wise construction followed by conversion to and from JSON"), &
51+
check_write_then_read_ptr) &
52+
]
53+
#endif
3854
associate( &
39-
descriptions => &
40-
[ character(len=len(longest_description)) :: &
41-
"component-wise construction followed by conversion to and from JSON" &
42-
], &
43-
outcomes => &
44-
[ write_then_read_hyperparameters() &
45-
] &
55+
substring_in_subject => index(subject(), test_description_substring) /= 0, &
56+
substring_in_description => test_descriptions%contains_text(string_t(test_description_substring)) &
4657
)
47-
call assert(size(descriptions) == size(outcomes),"hyperparameters_test_m(results): size(descriptions) == size(outcomes)")
48-
test_results = test_result_t(descriptions, outcomes)
58+
test_descriptions = pack(test_descriptions, substring_in_subject .or. substring_in_description)
4959
end associate
50-
60+
test_results = test_descriptions%run()
5161
end function
5262

5363
function write_then_read_hyperparameters() result(test_passes)
Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ module inference_engine_test_m
66
! External dependencies
77
use assert_m, only : assert
88
use kind_parameters_m, only : rkind
9-
use sourcery_m, only : string_t, test_t, test_result_t, file_t
9+
use sourcery_m, only : test_t, test_result_t, test_description_t, test_description_substring, string_t, file_t
10+
#ifdef __GFORTRAN__
11+
use sourcery_m, only : test_function_i
12+
#endif
1013

1114
! Internal dependencies
1215
use inference_engine_m, only : inference_engine_t, tensor_t, difference_t
@@ -31,25 +34,33 @@ pure function subject() result(specimen)
3134

3235
function results() result(test_results)
3336
type(test_result_t), allocatable :: test_results(:)
34-
35-
character(len=*), parameter :: longest_description = &
36-
"converting a network with 2 hidden layers to and from JSON format"
37-
37+
type(test_description_t), allocatable :: test_descriptions(:)
38+
39+
#ifndef __GFORTRAN__
40+
test_descriptions = [ &
41+
test_description_t("performing elemental inference with 1 hidden layer", elemental_infer_with_1_hidden_layer_xor_net), &
42+
test_description_t("performing elemental inference with 2 hidden layers", elemental_infer_with_2_hidden_layer_xor_net), &
43+
test_description_t("converting a network with 2 hidden layers to and from JSON format", multi_hidden_layer_net_to_from_json) &
44+
]
45+
#else
46+
procedure(test_function_i), pointer :: elemental_infer_1_ptr, elemental_infer_2_ptr, multi_hidden_ptr
47+
elemental_infer_1_ptr => elemental_infer_with_1_hidden_layer_xor_net
48+
elemental_infer_2_ptr => elemental_infer_with_2_hidden_layer_xor_net
49+
multi_hidden_ptr => multi_hidden_layer_net_to_from_json
50+
51+
test_descriptions = [ &
52+
test_description_t("performing elemental inference with 1 hidden layer", elemental_infer_1_ptr), &
53+
test_description_t("performing elemental inference with 2 hidden layers", elemental_infer_2_ptr), &
54+
test_description_t("converting a network with 2 hidden layers to and from JSON format", multi_hidden_ptr) &
55+
]
56+
#endif
3857
associate( &
39-
descriptions => &
40-
[ character(len=len(longest_description)) :: &
41-
"performing elemental inference with 1 hidden layer", &
42-
"performing elemental inference with 2 hidden layers", &
43-
"converting a network with 2 hidden layers to and from JSON format" &
44-
], &
45-
outcomes => &
46-
[ elemental_infer_with_1_hidden_layer_xor_net(), elemental_infer_with_2_hidden_layer_xor_net(), &
47-
multi_hidden_layer_net_to_from_json() &
48-
] &
58+
substring_in_subject => index(subject(), test_description_substring) /= 0, &
59+
substring_in_description => test_descriptions%contains_text(string_t(test_description_substring)) &
4960
)
50-
call assert(size(descriptions) == size(outcomes), "inference_engine_test(results): size(descriptions) == size(outcomes)")
51-
test_results = test_result_t(descriptions, outcomes)
61+
test_descriptions = pack(test_descriptions, substring_in_subject .or. substring_in_description)
5262
end associate
63+
test_results = test_descriptions%run()
5364
end function
5465

5566
function single_hidden_layer_xor_network() result(inference_engine)
@@ -98,7 +109,7 @@ function distinct_parameters() result(inference_engine)
98109
end function
99110

100111
function multi_hidden_layer_net_to_from_json() result(test_passes)
101-
logical, allocatable :: test_passes
112+
logical test_passes
102113
type(inference_engine_t) inference_engine, from_json
103114
type(file_t) json_file
104115
type(difference_t) difference
@@ -112,7 +123,7 @@ function multi_hidden_layer_net_to_from_json() result(test_passes)
112123
end function
113124

114125
function elemental_infer_with_1_hidden_layer_xor_net() result(test_passes)
115-
logical, allocatable :: test_passes(:)
126+
logical test_passes
116127
type(inference_engine_t) inference_engine
117128

118129
inference_engine = single_hidden_layer_xor_network()
@@ -125,15 +136,15 @@ function elemental_infer_with_1_hidden_layer_xor_net() result(test_passes)
125136
associate(array_of_inputs => [tensor_t([true,true]), tensor_t([true,false]), tensor_t([false,true]), tensor_t([false,false])])
126137
truth_table = inference_engine%infer(array_of_inputs)
127138
end associate
128-
test_passes = [ &
139+
test_passes = all( &
129140
abs(truth_table(1)%values() - false) < tolerance .and. abs(truth_table(2)%values() - true) < tolerance .and. &
130141
abs(truth_table(3)%values() - true) < tolerance .and. abs(truth_table(4)%values() - false) < tolerance &
131-
]
142+
)
132143
end block
133144
end function
134145

135146
function elemental_infer_with_2_hidden_layer_xor_net() result(test_passes)
136-
logical, allocatable :: test_passes(:)
147+
logical test_passes
137148
type(inference_engine_t) inference_engine
138149

139150
inference_engine = multi_layer_xor_network()
@@ -146,10 +157,10 @@ function elemental_infer_with_2_hidden_layer_xor_net() result(test_passes)
146157
associate(array_of_inputs => [tensor_t([true,true]), tensor_t([true,false]), tensor_t([false,true]), tensor_t([false,false])])
147158
truth_table = inference_engine%infer(array_of_inputs)
148159
end associate
149-
test_passes = [ &
160+
test_passes = all( &
150161
abs(truth_table(1)%values() - false) < tolerance .and. abs(truth_table(2)%values() - true) < tolerance .and. &
151162
abs(truth_table(3)%values() - true) < tolerance .and. abs(truth_table(4)%values() - false) < tolerance &
152-
]
163+
)
153164
end block
154165
end function
155166

test/main.f90

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ program main
88
use network_configuration_test_m, only : network_configuration_test_t
99
use training_configuration_test_m, only : training_configuration_test_t
1010
use tensor_range_test_m, only : tensor_range_test_t
11+
use sourcery_m, only : command_line_t
1112
implicit none
1213

1314
type(inference_engine_test_t) inference_engine_test
@@ -21,15 +22,28 @@ program main
2122

2223
integer :: passes=0, tests=0
2324

25+
print_usage_if_help_requested: &
26+
block
27+
type(command_line_t) command_line
28+
character(len=*), parameter :: usage = &
29+
new_line('') // new_line('') // &
30+
'Usage: fpm test -- [--help] | [--contains <substring>]' // &
31+
new_line('') // new_line('') // &
32+
'where square brackets ([]) denote optional arguments, a pipe (|) separates alternative arguments,' // new_line('') // &
33+
'angular brackets (<>) denote a user-provided value, and passing a substring limits execution to' // new_line('') // &
34+
'the tests with test subjects or test descriptions containing the user-specified substring.' // new_line('')
35+
if (command_line%argument_present([character(len=len("--help"))::"--help","-h"])) stop usage
36+
end block print_usage_if_help_requested
37+
2438
call cpu_time(t_start)
2539
call random_init(repeatable=.true.,image_distinct=.true.)
2640
call hyperparameters_test%report(passes, tests)
2741
call network_configuration_test%report(passes, tests)
2842
call training_configuration_test%report(passes, tests)
43+
call tensor_range_test%report(passes, tests)
2944
call asymmetric_engine_test%report(passes, tests)
3045
call inference_engine_test%report(passes, tests)
3146
call trainable_engine_test%report(passes, tests)
32-
call tensor_range_test%report(passes, tests)
3347
call cpu_time(t_finish)
3448

3549
print *

test/network_configuration_test_m.F90

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ module network_configuration_test_m
44
!! Test network_configuration_t object I/O and construction
55

66
! External dependencies
7-
use assert_m, only : assert
8-
use sourcery_m, only : string_t, test_t, test_result_t, file_t
97
use inference_engine_m, only : network_configuration_t
8+
use sourcery_m, only : test_t, test_result_t, test_description_t, test_description_substring, string_t, file_t
9+
#ifdef __GFORTRAN__
10+
use sourcery_m, only : test_function_i
11+
#endif
1012

1113
! Internal dependencies
1214
use network_configuration_m, only : network_configuration_t
13-
1415
implicit none
1516

1617
private
@@ -31,24 +32,31 @@ pure function subject() result(specimen)
3132

3233
function results() result(test_results)
3334
type(test_result_t), allocatable :: test_results(:)
35+
type(test_description_t), allocatable :: test_descriptions(:)
3436

35-
character(len=*), parameter :: longest_description = &
36-
"component-wise construction followed by conversion to and from JSON"
37+
#ifndef __GFORTRAN__
38+
test_descriptions = [ &
39+
test_description_t( &
40+
string_t("component-wise construction followed by conversion to and from JSON"), &
41+
write_then_read_network_configuration) &
42+
]
43+
#else
44+
procedure(test_function_i), pointer :: check_write_then_read_ptr
45+
check_write_then_read_ptr => write_then_read_network_configuration
3746

47+
test_descriptions = [ &
48+
test_description_t( &
49+
string_t("component-wise construction followed by conversion to and from JSON"), &
50+
check_write_then_read_ptr) &
51+
]
52+
#endif
3853
associate( &
39-
descriptions => &
40-
[ character(len=len(longest_description)) :: &
41-
"component-wise construction followed by conversion to and from JSON" &
42-
], &
43-
outcomes => &
44-
[ write_then_read_network_configuration() &
45-
] &
54+
substring_in_subject => index(subject(), test_description_substring) /= 0, &
55+
substring_in_description => test_descriptions%contains_text(string_t(test_description_substring)) &
4656
)
47-
call assert(size(descriptions) == size(outcomes), &
48-
"network_configuration_test_m(results): size(descriptions) == size(outcomes)")
49-
test_results = test_result_t(descriptions, outcomes)
57+
test_descriptions = pack(test_descriptions, substring_in_subject .or. substring_in_description)
5058
end associate
51-
59+
test_results = test_descriptions%run()
5260
end function
5361

5462
function write_then_read_network_configuration() result(test_passes)

0 commit comments

Comments
 (0)