Testing: improve macros
authorTimePath <andrew.hardaker1995@gmail.com>
Mon, 4 Jan 2016 09:18:46 +0000 (20:18 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Mon, 4 Jan 2016 10:35:00 +0000 (21:35 +1100)
.gitlab-ci.yml
qcsrc/common/command/generic.qc
qcsrc/lib/test.qc
qcsrc/lib/test.qh
qcsrc/lib/yenc.qh
qcsrc/menu/xonotic/slider_decibels.qc

index 7de5568c1ff2c9d9c0f957ffd00eb88a8bf85b3b..bd671bf5c266cbb29a295bbd31951c241df55c84 100644 (file)
@@ -18,5 +18,5 @@ build:
     - while read line; do
         echo $line;
         if [[ $line == "All tests OK" ]]; then exit 0; fi;
-      done < <(${ENGINE} +map gitlab-ci +sv_cmd runtest +exit)
+      done < <(${ENGINE} +developer 1 +map gitlab-ci +sv_cmd runtest +exit)
     - exit 1
index 378d8c8c625098df1fa6bebb57d9663ef4e1184e..5b53592831e8832154eea0220e4cace928af910d 100644 (file)
@@ -495,7 +495,7 @@ void GenericCommand_runtest(float request, float argc)
                                        TEST_Run(argv(i));
                        }
                        else
-                               TEST_RunAll();
+                               RUN_ALL_TESTS();
                        return;
                }
 
index 1a71c7529705f7f99c7bd8bf55dd0067a1d8d1e0..41e1f294ae4c7eb0fc48684490e02615eba4c9e7 100644 (file)
@@ -1,22 +1,7 @@
 #include "test.qh"
 
-int TEST_failed;
-bool TEST_ok;
-
-void TEST_Fail(string cond)
-{
-       LOG_INFOF("Assertion failed: %s", cond);
-       // backtrace();
-       ++TEST_failed;
-}
-
-void TEST_OK()
-{
-       TEST_ok = true;
-}
-
 int TEST_RunAll_accumulated(int init);
-bool TEST_RunAll()
+bool RUN_ALL_TESTS()
 {
        int f = TEST_RunAll_accumulated(0);
        if (f)
@@ -35,6 +20,7 @@ bool TEST_Run(string s)
 {
        LOG_INFOF("%s: testing...\n", s);
        TEST_failed = 0;
+       TEST_fatal = 0;
        TEST_ok = false;
        callfunction(strcat("_TEST_", s));
        if (TEST_failed > 0)
index 9173696bf8cde5e2f48693bf3eff921130a8b1f8..af00f979ca0175dd8a5316e64525763b819adbf4 100644 (file)
@@ -1,5 +1,8 @@
 #pragma once
 
+// public:
+
+/** Use UpperCamelCase for suite and test only */
 #define TEST(suite, test) \
        void _TEST_##suite##_##test(); \
        [[accumulate]] int TEST_RunAll_accumulated(int f) { \
        } \
        void _TEST_##suite##_##test()
 
-#define TEST_Check(cond) MACRO_BEGIN { if (!(cond)) TEST_Fail(#cond); } MACRO_END
+/** Must be present at the end of a test */
+#define SUCCEED() (TEST_ok = true)
+
+/** Add a failure, but continue */
+#define ADD_FAILURE(msg) MACRO_BEGIN { ++TEST_failed; LOG_WARNINGF(msg); } MACRO_END
+
+/** Add a failure and return */
+#define FAIL(msg) _TEST_ASSERT(ADD_FAILURE(msg))
+
+#define HasFatalFailure() (TEST_fatal > 0)
+
+bool RUN_ALL_TESTS();
+
+// difference between expect/assert: assert returns early
+
+#define EXPECT_EQ(expected_, actual_) MACRO_BEGIN { \
+       int expected = expected_; \
+       int actual = actual_; \
+       if ((expected) != (actual)) { \
+               ADD_FAILURE(sprintf( \
+                       "Value of: " #actual_ "\n" \
+                       "  Actual: %d\n" \
+                       "Expected: %d\n", \
+                       actual, expected \
+               )); \
+       } \
+} MACRO_END
+#define ASSERT_EQ(expected, actual) _TEST_ASSERT(EXPECT_EQ(expected, actual))
+
+#define EXPECT_TRUE(condition) EXPECT_EQ(true, condition)
+#define ASSERT_TRUE(condition) ASSERT_EQ(true, condition)
+
+#define EXPECT_FALSE(condition) EXPECT_EQ(false, condition)
+#define ASSERT_FALSE(condition) ASSERT_EQ(false, condition)
 
-void TEST_OK();
-void TEST_Fail(string cond);
+#define EXPECT_NE(val1, val2) EXPECT_TRUE(val1 != val2)
+#define ASSERT_NE(val1, val2) _TEST_ASSERT(EXPECT_NE(val1, val2))
+
+#define EXPECT_LT(val1, val2) EXPECT_TRUE(val1 < val2)
+#define ASSERT_LT(val1, val2) _TEST_ASSERT(EXPECT_LT(val1, val2))
+
+#define EXPECT_LE(val1, val2) EXPECT_TRUE(val1 <= val2)
+#define ASSERT_LE(val1, val2) _TEST_ASSERT(EXPECT_LE(val1, val2))
+
+#define EXPECT_GT(val1, val2) EXPECT_TRUE(val1 > val2)
+#define ASSERT_GT(val1, val2) _TEST_ASSERT(EXPECT_GT(val1, val2))
+
+#define EXPECT_GE(val1, val2) EXPECT_TRUE(val1 >= val2)
+#define ASSERT_GE(val1, val2) _TEST_ASSERT(EXPECT_GE(val1, val2))
+
+#define EXPECT_NO_FATAL_FAILURE(statement) EXPECT_NO_FATAL_FAILURE_(statement, { })
+#define ASSERT_NO_FATAL_FAILURE(statement) EXPECT_NO_FATAL_FAILURE_(statement, { ++TEST_fatal; return; })
+
+// private:
 
-bool TEST_RunAll();
 bool TEST_Run(string test);
+int TEST_fatal;
+bool TEST_ok;
+int TEST_failed;
+
+#define _TEST_ASSERT(statement) \
+       MACRO_BEGIN { \
+               LAMBDA(statement); \
+               ++TEST_fatal; return; \
+       } MACRO_END
+
+#define EXPECT_NO_FATAL_FAILURE__(statement, then) \
+       MACRO_BEGIN { \
+               int TEST_prevfatal = TEST_fatal; \
+               LAMBDA(statement); \
+               if (TEST_fatal != TEST_prevfatal) \
+                       LAMBDA(then); \
+       } MACRO_END
+
+#define EXPECT_NO_FATAL_FAILURE_(statement, then) \
+       EXPECT_NO_FATAL_FAILURE__(statement, { \
+               LOG_WARNINGF( \
+                       "  Actual: %d fatal failures\n" \
+                       "Expected: no fatal failures\n", \
+                       TEST_fatal - TEST_prevfatal \
+               ); \
+               LAMBDA(then); \
+       })
index a9d9ed1f1fbb8c24c6b416c06058c6927b5c54f9..a8389e240f4e9ec0041ae5609a75c2ee9baae84a 100644 (file)
@@ -59,7 +59,7 @@ TEST(yEnc, EncodeDecode)
                STRING_ITERATOR(fragmentiterator, fragment, 0);
                ydec_single(fragmentiterator, encdec);
 
-               TEST_Check(encdec == expect);
+               EXPECT_EQ(expect, encdec);
        }
-       TEST_OK();
+       SUCCEED();
 }
index f34528da6f53803b845c5139520d9d8e66751ad4..c3eb4b0abd1cf2226480eeba3176c4a22a91f631 100644 (file)
@@ -97,7 +97,7 @@ string XonoticDecibelsSlider_valueToText(entity me, float v)
 bool autocvar_test_XonoticDecibelsSlider = false;
 TEST(XonoticDecibelsSlider, SoundTest)
 {
-       if (!autocvar_test_XonoticDecibelsSlider) { TEST_OK(); return; }
+       if (!autocvar_test_XonoticDecibelsSlider) { SUCCEED(); return; }
        for (int i = -400; i < 0; ++i)
        {
                float db = i * 0.1;
@@ -105,9 +105,9 @@ TEST(XonoticDecibelsSlider, SoundTest)
                float dbv = toDecibelOfSquare(v, -40);
                float d = dbv - db;
                LOG_INFOF("%f -> %f -> %f (diff: %f)\n", db, v, dbv, d);
-               TEST_Check(fabs(d) > 0.02);
+               EXPECT_GT(fabs(d), 0.02);
        }
-       TEST_OK();
+       SUCCEED();
 }
 
 #endif