]> Dogcows Code - chaz/vimcoder/commitdiff
generate TAP output with the default C++ templates
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Sun, 7 Apr 2013 20:21:43 +0000 (14:21 -0600)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Sun, 7 Apr 2013 21:22:13 +0000 (15:22 -0600)
README.md
src/com/dogcows/resources/C++Driver
src/com/dogcows/resources/C++Makefile

index 7068851fce9ff93f855ad1300b2b7278a012dc7a..0872d107c5058bf6a4ec913a84297ee6089df437 100644 (file)
--- a/README.md
+++ b/README.md
@@ -182,8 +182,7 @@ template.
 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
@@ -210,6 +209,13 @@ set to C++, the driver code would be in the driver.cc file.  You normally
 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.
 
index 460916b183d339134344ca1549ce876b482c9b0b..d08ded83b4928fece0f931c07dd65dcca23eb603 100644 (file)
@@ -11,8 +11,6 @@
 #include <sys/time.h>
 #include <vector>
 
-using namespace std;
-
 
 const static double __EPSILON = 1e-9;
 static double __time = 0.0;
@@ -126,11 +124,17 @@ bool __equals(double actual, double expected)
 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;
 }
@@ -144,50 +148,57 @@ int main(int argc, char* argv[])
 
        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;
index 68c794a6fb2034293e5ebcffc75c9583c5a45d9b..3406fb0cef4a2f1ae9a6b377e416bee397c427ad 100644 (file)
@@ -1,26 +1,42 @@
 
+# 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
This page took 0.039404 seconds and 4 git commands to generate.