doctest

FORK: The fastest feature-rich C++11/14/17/20 single-header testing framework
git clone https://git.neptards.moe/neptards/doctest.git
Log | Files | Refs | README

reporters.html (4985B)


      1 <!DOCTYPE html>
      2 <html>
      3 <title>reporters</title>
      4 <xmp theme="united" style="display:none;">
      5 
      6 ## Reporters
      7 
      8 Doctest has a modular reporter/listener system with which users can write their own reporters and register them. The reporter interface can also be used for "listening" to events.
      9 
     10 You can list all registered reporters/listeners with ```--list-reporters```. There are a few implemented reporters in the framework:
     11 - ```console``` - streaming - writes normal lines of text with coloring if a capable terminal is detected
     12 - ```xml``` - streaming - writes in xml format tailored to doctest
     13 - ```junit``` - buffering - writes in JUnit-compatible xml - for more information look [here](https://github.com/doctest/doctest/issues/318) and [here](https://github.com/doctest/doctest/issues/376).
     14 
     15 Streaming means that results are delivered progressively and not at the end of the test run.
     16 
     17 The output is by default written to ```stdout``` but can be redirected with the use of the ```--out=<filename>``` [**command line option**](commandline.html).
     18 
     19 Example how to define your own reporter:
     20 
     21 ```
     22 #include <doctest/doctest.h>
     23 
     24 #include <mutex>
     25 
     26 using namespace doctest;
     27 
     28 struct MyXmlReporter : public IReporter
     29 {
     30     // caching pointers/references to objects of these types - safe to do
     31     std::ostream&         stdout_stream;
     32     const ContextOptions& opt;
     33     const TestCaseData*   tc;
     34     std::mutex            mutex;
     35 
     36     // constructor has to accept the ContextOptions by ref as a single argument
     37     MyXmlReporter(const ContextOptions& in)
     38             : stdout_stream(*in.cout)
     39             , opt(in) {}
     40 
     41     void report_query(const QueryData& /*in*/) override {}
     42 
     43     void test_run_start() override {}
     44 
     45     void test_run_end(const TestRunStats& /*in*/) override {}
     46 
     47     void test_case_start(const TestCaseData& in) override { tc = &in; }
     48 
     49     // called when a test case is reentered because of unfinished subcases
     50     void test_case_reenter(const TestCaseData& /*in*/) override {}
     51 
     52     void test_case_end(const CurrentTestCaseStats& /*in*/) override {}
     53 
     54     void test_case_exception(const TestCaseException& /*in*/) override {}
     55 
     56     void subcase_start(const SubcaseSignature& /*in*/) override {
     57         std::lock_guard<std::mutex> lock(mutex);
     58     }
     59 
     60     void subcase_end() override {
     61         std::lock_guard<std::mutex> lock(mutex);
     62     }
     63 
     64     void log_assert(const AssertData& in) override {
     65         // don't include successful asserts by default - this is done here
     66         // instead of in the framework itself because doctest doesn't know
     67         // if/when a reporter/listener cares about successful results
     68         if(!in.m_failed && !opt.success)
     69             return;
     70 
     71         // make sure there are no races - this is done here instead of in the
     72         // framework itself because doctest doesn't know if reporters/listeners
     73         // care about successful asserts and thus doesn't lock a mutex unnecessarily
     74         std::lock_guard<std::mutex> lock(mutex);
     75 
     76         // ...
     77     }
     78 
     79     void log_message(const MessageData& /*in*/) override {
     80         // messages too can be used in a multi-threaded context - like asserts
     81         std::lock_guard<std::mutex> lock(mutex);
     82 
     83         // ...
     84     }
     85 
     86     void test_case_skipped(const TestCaseData& /*in*/) override {}
     87 };
     88 
     89 // "1" is the priority - used for ordering when multiple reporters are used
     90 REGISTER_REPORTER("my_xml", 1, MyXmlReporter);
     91 
     92 // registering the same class as a reporter and as a listener is nonsense but it's possible
     93 REGISTER_LISTENER("my_listener", 1, MyXmlReporter);
     94 ```
     95 
     96 Custom `IReporter` implementations must be registered with one of:
     97 
     98 * `REGISTER_REPORTER`, for when the new reporter is an option that users may choose at run-time.
     99 * `REGISTER_LISTENER`, for when the reporter is actually a listener and must always be executed, regardless of which reporters have been chosen at run-time.
    100 
    101 Multiple reporters can be used at the same time - just specify them through the ```--reporters=...``` [**command line filtering option**](commandline.html) using commas to separate them like this: ```--reporters=myReporter,xml``` and their order of execution will be based on their priority - that is the number "1" in the case of the example reporter above (lower means earlier - the default console/xml reporters from the framework have 0 as their priority and negative numbers are accepted as well).
    102 
    103 All registered listeners (```REGISTER_LISTENER```) will be executed before any reporter - they do not need to be specified and cannot be filtered through the command line.
    104 
    105 When implementing a reporter users are advised to follow the comments from the example above and look at the few implemented reporters in the framework itself. Also check out the [**example**](../../examples/all_features/reporters_and_listeners.cpp).
    106 
    107 ---------------
    108 
    109 [Home](readme.html#reference)
    110 
    111 <p align="center"><img src="../../scripts/data/logo/icon_2.svg"></p>
    112 
    113 
    114 </xmp>
    115 <script src="strapdown.js/strapdown.js"></script>
    116 </html>