If you are using the default Makefile template for C++, typing ":make" without
any arguments will compile your code. Typing ":make run" will run all of the
test cases against your code. Typing ":make test" will also run the test
-cases against your code, up until the first failed test at which point it will
-abort.
+cases against your code, except it will abort at the first failed test.
A Makefile template is not yet provided for any other language, but you can
write one yourself if you are so inclined. Read on to learn how templates
don't have to do anything with this file. It just provides supporting code
for running the test cases against your code.
+The driver should output TAP (Test Anything Protocol) so that tests can be run
+in a test harness such as [prove](http://search.cpan.org/perldoc?prove). The
+default Makefile template has a `prove` target (type ":make prove") that can
+run the tests in a test harness; the test harness is `prove` unless otherwise
+configured. TAP output is also very human-readable all by itself, so having
+a test harness isn't really required.
+
A default driver template is currently only provided for the C++ language.
You could write your own template if you wanted to.
#include <sys/time.h>
#include <vector>
-using namespace std;
-
const static double __EPSILON = 1e-9;
static double __time = 0.0;
bool __equals(const std::vector<double>& actual, const std::vector<double>& expected)
{
if (actual.size() != expected.size())
+ {
return false;
+ }
for (size_t i = 0; i < actual.size(); ++i)
+ {
if (!__equals(actual[i], expected[i]))
+ {
return false;
+ }
+ }
return true;
}
if (1 < argc) __abort_on_fail = true;
+ std::cout << "TAP version 13" << std::endl;
+ std::cout.flush();
+
std::ifstream __in("testcases.txt");
for(;;)
{
+ int __testnum = __pass + __fail + 1;
+
$RETURNTYPE$ __expected;
$METHODPARAMDECLARES$
__in >> __expected >> $METHODPARAMSTREAMIN$;
if (!__in.good()) break;
- std::cout << "----------------------------------------" << std::endl
- << "Test " << (__pass + __fail) << ": ";
+ std::cout << "# input for test " << __testnum << ": " << $METHODPARAMSTREAMOUT$ << std::endl;
std::cout.flush();
__timer_start();
- $CLASSNAME$ object;
- $RETURNTYPE$ __actual = object.$METHODNAME$($METHODPARAMNAMES$);
+ $CLASSNAME$ __object;
+ $RETURNTYPE$ __actual = __object.$METHODNAME$($METHODPARAMNAMES$);
double __t = __timer_stop();
+ std::cout << "# test completed in " << __t << " seconds" << std::endl;
+ std::cout.flush();
+
if (__equals(__actual, __expected))
{
- std::cout << "[PASS] in " << __t << " seconds." << std::endl;
+ std::cout << "ok";
++__pass;
}
else
{
- std::cout << "[FAIL] in " << __t << " seconds." << std::endl
- << "-> Input: " << $METHODPARAMSTREAMOUT$ << std::endl
- << " Actual: " << __actual << std::endl
- << " Expected: " << __expected << std::endl;
+ std::cout << "not ok";
++__fail;
- if (__abort_on_fail) std::abort();
}
+
+ std::cout << " " << __testnum << " - " << __actual << " must equal " << __expected << std::endl;
+ std::cout.flush();
+
+ if (__abort_on_fail && 0 < __fail) std::abort();
}
- std::cout << "========================================" << std::endl
- << " Total Pass: " << __pass << std::endl
- << " Total Fail: " << __fail << std::endl;
+ std::cout << "1.." << (__pass + __fail) << std::endl
+ << "# passed: " << __pass << std::endl
+ << "# failed: " << __fail << std::endl;
if (__fail == 0)
{
- std::cout << std::endl << "Nice! "
- << "Don't forget to compile remotely before submitting."
- << std::endl;
+ std::cout << std::endl
+ << "# Nice! Don't forget to compile remotely before submitting." << std::endl;
}
return __fail;
+# Set the command for your C++ compiler, and specify any compiler flags you
+# want to use (e.g. -g -Werror).
CXX = g++
-CXXFLAGS = -O0 -ggdb -Wall
+CXXFLAGS = -ggdb -Wall
-all: driver
+# The driver outputs TAP (Test Anything Protocol), so it can also be used with
+# any TAP test harness (e.g. prove). Set the path to your test harness here,
+# then use the `prove' target to run the tests with that harness.
+PROVE = prove
+PROVEFLAGS = -e ""
-run: all
- ./driver
-test: all
- ./driver -exit_on_fail
+ifeq ($(OS),Windows_NT)
+EXEEXT = .exe
+endif
-driver.o: $CLASSNAME$.o
-driver: driver.o
- $(CXX) $(CXXFLAGS) $< -o $@ $(LDFLAGS) $(LDLIBS)
+all: driver$(EXEEXT)
clean:
- rm -f $CLASSNAME$.o driver.o driver
+ rm -f driver$(EXEEXT)
distclean: clean
rm -f $CLASSNAME$
-.PHONY: all run test clean distclean
+run: all
+ ./driver$(EXEEXT)
+
+test: all
+ ./driver$(EXEEXT) --abort-on-fail
+
+prove: all
+ $(PROVE) $(PROVEFLAGS) ./driver$(EXEEXT)
+
+
+%$(EXEEXT): %.cc
+ $(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@
+
+.PHONY: all clean distclean run test prove
# vim:ft=make:noet:ts=8