I am trying to set dependencies in the Boost Unit Testing Framework. I have found this thread tbat has an example of how to use the test_unit::depends_on() method. So far so good, I can write some magickery around that to smooth it out. However, the UTF doesn't honor test dependencies during execution.
Scenario: A BOOST_AUTO_TEST_CASE A is declared before another (B), and A depends_on() B Excpected (desired) outcome: The framework detects the dependency and runs B first, and then A if B succeeded. Actual Outcome: A is skipped because B, which has not run yet, has "failed" (i.e. no/false result yet).
Now, my idea was to do a topological sort on the test cases / suites and then run them in the sorted order. For that, I created a test_tree_visitor to walk the suites and determine the order of the m_members test_suite member.
However, m_members is protected and not accessible via methods. Since I can't change the headers, (would make upgrading to a newer version more difficult, etc, etc), and the BOOST_* macros "hardcode" the class as test_suite, I was thinking about the following hackery:
class member_accessible_test_suite : public test_suite
{
public:
const std::vector<test_unit_id> *get_members() const { return &m_members; }
};
class dependency_order_visitor : public test_tree_visitor
{
public:
virtual void visit( test_case const& tu)
{}
virtual bool test_suite_start( test_suite const& tu)
{
const member_accessible_test_suite *psuite(reinterpret_cast<const member_accessible_test_suite*>(&tu));
const std::vector<test_unit_id> *pmembers(psuite->get_members());
/* do something with pmembers */
return true;
}
virtual void test_suite_finish( test_suite const& tu)
{}
};
See a watered down version on Coliru
So now to my questions:
The boost libraries are generally well designed - am I making a fundamental mistake due to a misunderstanding about unit testing design by requiring this feature?
Since member_accessible_test_suite has no data and adds only functions, is the reinterpret_cast() safe or the fast lane into UB land? Either way, I am worried to use such a ghastly hack in production.
Is there a better way, and if so, at which point did this turn into an XY problem?
The following way seems the most proper when dealing with base class members that are not exposed via any mechanism (but must be accessed for some close functionality, and the base class must not be modified):
Link: Access to private member variables
The reasoning behind this idea as to why this works can be found in the 14.7.2p8 of the standard:
I took the liberty to outsource this into two macros that may come in handy again one day.
As with all of these workarounds - use wisely!