Unit Test Framework
Neither MT4 nor MT5 has a test runner or an exit code a CI step can read. The usual habit is a handful of Print() calls with a comment like "should be 5" beside them, which works until either the code or the comment changes and nobody notices they have drifted apart. There is also no running total, so a script with forty of these tells you nothing about how many actually held true. This header keeps four counters - total, passed, failed, and the first failure message - and updates them every time a check runs. Each check prints its own PASS or FAIL line with the actual and expected values inline, so a failure is legible without stepping through the code in a debugger, and the final summary line gives a single pass/fail count worth screenshotting. Test cases are plain void functions taking no arguments. They are collected into an array of function pointers and handed to UnitTestRunSuite(), which runs them in order and prints the suite header and footer around them. Each case opens with UnitTestBeginCase() so failures are attributed to the right case without threading a name argument through every single check - the label is set once and every check after it inherits it until the next case begins. The state is deliberately file-scope rather than a class. Neither platform's function pointers can be bound to a class instance, so a suite runner that accepts bare test-case functions has nowhere else to keep the counters. A check made before any case has opened is still recorded, filed under "Unnamed" rather than lost, because a missing label is a documentation gap, not a reason to drop a result. This is a counting and reporting layer, not a mocking framework or an assertion library on its own - UnitTestCheck() takes any boolean expression, so it composes with whatever comparison logic the test needs, including Assertions.mqh if that is already part of the project (as a separate #include, not a dependency of this header - each CodeBase submission stands alone). Notes and limitations - The framework has no setup/teardown hooks and no test isolation - counters are shared file-scope state, so two suites run back to back accumulate into the same totals unless UnitTestReset() is called between them. - Test-case functions take no arguments and return nothing, which is a limitation of both platforms' function pointers, not a design choice - there is no way to pass fixtures into a case beyond global or input variables. - This is a counting and reporting tool, not a mocking or stubbing framework. Testing anything that depends on live account or market state (a trade call, account balance) still needs the caller to structure the code so the parts under test do not require a live connection. - Not reentrant across chart instances - two EAs on different charts sharing this header each get their own compiled copy of the file-scope counters, so there is no cross-chart interference, but a single program calling the suite from two places concurrently (e.g. OnTick and OnTimer) would need its own synchronisation, which the single-threaded-per-chart model on both platforms makes a non-issue in practice.
Script · MT5 · v1.0 · Free
About Unit Test Framework
Unit Test Framework is a script for MetaTrader 5. MQL source code included.
Files in the download: UnitTest.mq5.mqh, UnitTest.txt, UnitTestDemo.ex5, UnitTestDemo.mq5.
How to install
- Download the ZIP from your PolyMaria library and unzip it.
- In MetaTrader 5 open File → Open Data Folder, then go to MQL5 → Scripts.
- Copy the .mq5 file(s) there. Put any .mqh files in MQL5 → Include.
- Open the .mq5 file in MetaEditor and press Compile (F7) if MetaTrader does not show it.
- Drag the script onto a chart to run it once.
Tags: MT5 Script · MQL5 Source Code