About
--------
This is a tool for running a program many times with varying input, and checking the output against expected values. In this way a program's correctness can be tested, (hopefully) making the programmer more confident of the absence of bugs. It can also help with confirming no bugs have been introduced later on, and that fixed bugs stay fixed.
This was written as part of the L-BASIC project, but is fairly generic and should work with any program that takes a filename in COMMAND$ and prints output to the console (i.e. use $CONSOLE:ONLY). Thanks to
@Ed Davis for providing Windows compatibility patches.
Usage
---------
Let's say we have a simple program, save it as sample.bas and compile:
System 1 'Exit with an error if we read a Q
It reads a file and prints out the contents in upper case, but requires the input not contain the letter Q: that is considered invalid input and will give an error.
Now we can write some test cases! The format should be fairly clear; the file is one or more test cases, delimited with various $commands:
$title: Letters are uppercased
the rain in spain
$expect: stdout
THE RAIN IN SPAIN
$finish
$title: Uppercased letters stay uppercased
The rain in Spain
$expect: stdout
THE RAIN IN SPAIN
$finish
$title: Multi-line input
Now is the time for
all good men to
come to the aid
of their party
$expect: stdout
NOW IS THE TIME FOR
ALL GOOD MEN TO
COME TO THE AID
OF THEIR PARTY
$finish
$title: Bad input is caught
This has a Q in it
$expect: error
The structure is:
- Each test begins with $title to give the test an identifiying name.
- The contents of the input file is provided
- $expect: stdout indicates that we should check the standard (i.e. console) output of the program
- The expected output is provided
- $finish indicates the end of the expected output
If instead an error is expected, we can $expect: error. No expected output or $finish is required then.
$expect: stdout strips leading and trailing whitespace before comparing. Use $expect: stdout_exact if you don't want that.
Now you can run it (on Mac/Linux, use './sample'):
test-runner.exe sample.exe our-tests.txt
and get an output similar to this:
test:Letters are uppercased: OK
test:Uppercased letters stay uppercased: OK
test:Multi-line input: OK
test:Bad input is caught: OK
Total 4/4 OK in 4 seconds
If any test failed, it would show us the expected and actual output to help fix the program.
'Copyright 2020 Luke Ceddia
'SPDX-License-Identifier: Apache-2.0
'test.bas - Run test suite
Dim active_section
'0 = none, 1 = program, 2 = output
tmpdir$ = "/tmp/"
active_test
= UBound(tests
) + 1 tests
(active_test
).title
= basename$
(Command$(cmdline_index
)) + ":" + LTrim$(Mid$(lt$
, 8)) active_section = 1
active_section = 2
active_section = 0
tests
(active_test
).program
= tests
(active_test
).program
+ l$
+ Chr$(10) tests
(active_test
).expected_output
= tests
(active_test
).expected_output
+ l$
+ Chr$(10) 'Blank line or comment, do nothing
Print "Must start with $title"
starttime!
= Timer(0.001) 'print "TITLE: "; tests(active_test).title
'print "PROGRAM"
'print "-------"
'print tests(active_test).program;
'print "EXPECT: "; tests(active_test).expect
'print tests(active_test).expected_output;
filename$ = tmpdir$ + "test-" + rndhex$(4)
Print #1, tests
(active_test
).program
retcode
= Shell(testbinary$
+ " " + filename$
+ ".bas > " + filename$
+ ".output") Print tests
(active_test
).title;
": ";
successes = successes + 1
Print "Failed, expected error but ran successfully." Case "stdout", "stdout_exact" actual_output$
= remove_char$
(actual_output$
, Chr$(13)) tests
(active_test
).expected_output
= remove_char$
(tests
(active_test
).expected_output
, Chr$(13))
If tests
(active_test
).expect
<> "stdout_exact" Then actual_output$ = strip$(actual_output$)
tests(active_test).expected_output = strip$(tests(active_test).expected_output)
Print "Failed with error, output was: "; actual_output$
ElseIf actual_output$
= tests
(active_test
).expected_output
Then successes = successes + 1
Print "Expected: "; tests
(active_test
).expected_output;
Print " Actual: "; actual_output$;
Print "Unknown condition" Kill filename$
+ ".output"
ehandler:
basename$
= Mid$(path$
, slash
+ 1, dot
- slash
- 1)
rndhex$ = result$
'Courtesy Ed Davis
s2$ = ""
s2$
= s2$
+ Mid$(s$
, i
, 1) remove_char$ = s2$
start = 0
start = start + 1
finish = finish - 1
strip$
= Mid$(s$
, start
, finish
- start
+ 1)