//+------------------------------------------------------------------+ //| Warrior_EA | //| AnimateDread | //| | //| Shared PASS/FAIL harness for the unit-test EAs under Tests\. One | //| assertion helper and one summary line, so every test EA prints in | //| the same shape and a log grep for "FAIL:" or "ALL TESTS PASSED" | //| works identically across all of them. | //+------------------------------------------------------------------+ #ifndef WARRIOR_TESTS_TESTHARNESS_MQH #define WARRIOR_TESTS_TESTHARNESS_MQH int g_testPass = 0; int g_testFail = 0; //--- One assertion. Prints PASS/FAIL with the description so a failing line is self-explanatory //--- without cross-referencing this file against the source it is testing. void TAssert(const bool cond, const string what) { if(cond) { g_testPass++; Print("PASS: " + what); } else { g_testFail++; Print("FAIL: " + what); } } //--- Float/double equality within an absolute tolerance - exact == is the wrong test for anything //--- that passed through a division. bool TNear(const double a, const double b, const double eps = 1e-6) { return MathAbs(a - b) <= eps; } void TAssertNear(const double got, const double want, const string what, const double eps = 1e-6) { TAssert(TNear(got, want, eps), what + StringFormat(" (got %.10f, want %.10f, eps %.1e)", got, want, eps)); } //--- One line per suite, deliberately grep-able: "ALL TESTS PASSED" or "TESTS FAILED". void TSummary(const string suite) { PrintFormat("%s: SUMMARY %d passed, %d failed, %d total.", suite, g_testPass, g_testFail, g_testPass + g_testFail); if(g_testFail == 0) Print(suite + ": ALL TESTS PASSED"); else Print(suite + ": TESTS FAILED - see FAIL lines above"); } #endif // WARRIOR_TESTS_TESTHARNESS_MQH //+------------------------------------------------------------------+