239 lines
7.6 KiB
MQL5
239 lines
7.6 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| CAssert.mqh |
|
|
//| Synthetic Test Harness for MetaTrader 5 |
|
|
//| Institutional Architecture in MQL5 - Part 1 Series |
|
|
//+------------------------------------------------------------------+
|
|
#ifndef SYNTHETIC_TEST_HARNESS_CASSERT_MQH
|
|
#define SYNTHETIC_TEST_HARNESS_CASSERT_MQH
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| CAssert: Centralized self-validating assertions and reporting |
|
|
//| for MQL5 unit and scenario testing (FIRST principle). |
|
|
//+------------------------------------------------------------------+
|
|
class CAssert
|
|
{
|
|
private:
|
|
static int m_passed;
|
|
static int m_failed;
|
|
static string m_report;
|
|
|
|
public:
|
|
//--- Reset state before running test suites
|
|
static void Reset(void)
|
|
{
|
|
m_passed = 0;
|
|
m_failed = 0;
|
|
m_report = "";
|
|
}
|
|
|
|
//--- Logging helper: prints to Experts log and updates chart comments
|
|
static void Log(const string msg)
|
|
{
|
|
if(msg != "")
|
|
Print(msg);
|
|
m_report += msg + "\n";
|
|
Comment(m_report);
|
|
}
|
|
|
|
//--- Metrics getters
|
|
static int PassedCount(void) { return(m_passed); }
|
|
static int FailedCount(void) { return(m_failed); }
|
|
static int TotalCount(void) { return(m_passed + m_failed); }
|
|
static bool AllPassed(void) { return(m_failed == 0 && m_passed > 0); }
|
|
static string GetReport(void) { return(m_report); }
|
|
|
|
//--- Assert True: foundational assertion
|
|
static void True(const string test_name, const bool condition)
|
|
{
|
|
if(condition)
|
|
{
|
|
m_passed++;
|
|
PrintFormat(" [PASS] %s", test_name);
|
|
}
|
|
else
|
|
{
|
|
m_failed++;
|
|
PrintFormat(" [FAIL] %s", test_name);
|
|
}
|
|
}
|
|
|
|
//--- Assert False: inverted condition assertion
|
|
static void False(const string test_name, const bool condition)
|
|
{
|
|
True(test_name, !condition);
|
|
}
|
|
|
|
//--- Assert Equal (Double with tolerance)
|
|
static void Equal(const string test_name,
|
|
const double expected,
|
|
const double actual,
|
|
const double epsilon = 0.00001)
|
|
{
|
|
bool match = (MathAbs(expected - actual) < epsilon);
|
|
if(!match)
|
|
Log(StringFormat(" Expected=%.5f Actual=%.5f", expected, actual));
|
|
True(test_name, match);
|
|
}
|
|
|
|
static void DoubleEqual(const string test_name,
|
|
const double expected,
|
|
const double actual,
|
|
const double epsilon = 0.00001)
|
|
{
|
|
Equal(test_name, expected, actual, epsilon);
|
|
}
|
|
|
|
//--- Assert Integer Equal
|
|
static void IntEqual(const string test_name,
|
|
const int expected,
|
|
const int actual)
|
|
{
|
|
bool match = (expected == actual);
|
|
if(!match)
|
|
Log(StringFormat(" Expected=%d Actual=%d", expected, actual));
|
|
True(test_name, match);
|
|
}
|
|
|
|
//--- Assert Long Integer Equal
|
|
static void LongEqual(const string test_name,
|
|
const long expected,
|
|
const long actual)
|
|
{
|
|
bool match = (expected == actual);
|
|
if(!match)
|
|
Log(StringFormat(" Expected=%I64d Actual=%I64d", expected, actual));
|
|
True(test_name, match);
|
|
}
|
|
|
|
//--- Assert Unsigned Integer Equal
|
|
static void UintEqual(const string test_name,
|
|
const uint expected,
|
|
const uint actual)
|
|
{
|
|
bool match = (expected == actual);
|
|
if(!match)
|
|
Log(StringFormat(" Expected=%u Actual=%u", expected, actual));
|
|
True(test_name, match);
|
|
}
|
|
|
|
//--- Assert Unsigned Long Equal
|
|
static void UlongEqual(const string test_name,
|
|
const ulong expected,
|
|
const ulong actual)
|
|
{
|
|
bool match = (expected == actual);
|
|
if(!match)
|
|
Log(StringFormat(" Expected=%I64u Actual=%I64u", expected, actual));
|
|
True(test_name, match);
|
|
}
|
|
|
|
//--- Assert String Equal
|
|
static void StringEqual(const string test_name,
|
|
const string expected,
|
|
const string actual)
|
|
{
|
|
bool match = (expected == actual);
|
|
if(!match)
|
|
Log(StringFormat(" Expected=\"%s\" Actual=\"%s\"", expected, actual));
|
|
True(test_name, match);
|
|
}
|
|
|
|
//--- Display summary & MessageBox dialog
|
|
static void Summary(const string suite_title = "Test Results",
|
|
const bool show_message_box = true)
|
|
{
|
|
Log("");
|
|
Log("==========================================================");
|
|
string summary = StringFormat(" RESULTS: %d passed, %d failed, %d total",
|
|
m_passed, m_failed, TotalCount());
|
|
Log(summary);
|
|
|
|
string status;
|
|
uint icon;
|
|
if(m_failed == 0 && m_passed > 0)
|
|
{
|
|
status = " STATUS: ALL TESTS PASSED (100% SUCCESS)";
|
|
icon = MB_ICONINFORMATION;
|
|
}
|
|
else if(m_failed == 0 && m_passed == 0)
|
|
{
|
|
status = " STATUS: NO TESTS EXECUTED";
|
|
icon = MB_ICONWARNING;
|
|
}
|
|
else
|
|
{
|
|
status = " STATUS: SOME TESTS FAILED";
|
|
icon = MB_ICONERROR;
|
|
}
|
|
|
|
Log(status);
|
|
Log("==========================================================");
|
|
|
|
if(show_message_box)
|
|
MessageBox(summary + "\n\n" + status, suite_title, icon | MB_OK);
|
|
|
|
Comment("");
|
|
}
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Static member variable initialization |
|
|
//+------------------------------------------------------------------+
|
|
int CAssert::m_passed = 0;
|
|
int CAssert::m_failed = 0;
|
|
string CAssert::m_report = "";
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Global helper functions for functional assertion syntax |
|
|
//+------------------------------------------------------------------+
|
|
void Log(const string msg)
|
|
{
|
|
CAssert::Log(msg);
|
|
}
|
|
|
|
void AssertTrue(const string test_name, const bool condition)
|
|
{
|
|
CAssert::True(test_name, condition);
|
|
}
|
|
|
|
void AssertFalse(const string test_name, const bool condition)
|
|
{
|
|
CAssert::False(test_name, condition);
|
|
}
|
|
|
|
void AssertEqual(const string test_name, const double expected, const double actual, const double epsilon = 0.00001)
|
|
{
|
|
CAssert::Equal(test_name, expected, actual, epsilon);
|
|
}
|
|
|
|
void AssertDoubleEqual(const string test_name, const double expected, const double actual, const double epsilon = 0.00001)
|
|
{
|
|
CAssert::DoubleEqual(test_name, expected, actual, epsilon);
|
|
}
|
|
|
|
void AssertIntEqual(const string test_name, const int expected, const int actual)
|
|
{
|
|
CAssert::IntEqual(test_name, expected, actual);
|
|
}
|
|
|
|
void AssertLongEqual(const string test_name, const long expected, const long actual)
|
|
{
|
|
CAssert::LongEqual(test_name, expected, actual);
|
|
}
|
|
|
|
void AssertUintEqual(const string test_name, const uint expected, const uint actual)
|
|
{
|
|
CAssert::UintEqual(test_name, expected, actual);
|
|
}
|
|
|
|
void AssertUlongEqual(const string test_name, const ulong expected, const ulong actual)
|
|
{
|
|
CAssert::UlongEqual(test_name, expected, actual);
|
|
}
|
|
|
|
void AssertStringEqual(const string test_name, const string expected, const string actual)
|
|
{
|
|
CAssert::StringEqual(test_name, expected, actual);
|
|
}
|
|
|
|
#endif
|