Opened 12 years ago

Closed 5 years ago

Last modified 5 years ago

#5282 closed Feature Requests (wontfix)

Test fixtures do not support virtual inheritance

Reported by: tye.zdrojewski@… Owned by: Raffi Enficiaud
Milestone: To Be Determined Component: test
Version: Boost 1.45.0 Severity: Problem
Keywords: Cc:

Description

A typical use of fixtures for a test suite is to make it a subclass of the class under test (CUT) so that protected members can be accessed.

However, if the CUT has a virtual base class in its inheritance chain, the call to that class's constructor cannot be specified, because the fixture macros introduce another level of inheritance (sub-struct).

This means that we have to jump through some hoops to get to protected members.

It would be nice to have an argument to the FIXTURE macros that would allow the tester to specify some or all of the initialization list for the final class/struct in the inheritance chain.

Change History (11)

comment:1 by Gennadiy Rozental, 11 years ago

I am not sure I understand what the problem is. CUT is not a fixture. and why fixture needs virtual base classes is unclear. Please provide an example.

comment:2 by Tye Z. <tye.zdrojewski@…>, 11 years ago

Ok, so if I have a class TestMe...

class TestMe
{
protected:
   bool protectedValue = 0;
   int protectedMethod(int arg) { ... }
   void someProtectedBehavior() { ... }
}

I will usually create a fixture as a subclass:

/**
 * Override methods to add test functionality
 */
class TestMeFixture : public TestMe
{
   // override production behavior for testing 
   void someProtectedBehavior() { ... } 
}

BOOST_FIXTURE_TEST_SUITE( MyTestSuite, TestMeFixture )
BOOST_AUTO_TEST_CASE( test_top_level_values )
{
   int expected = 123;
   BOOST_CHECK_EQUAL(expected, protectedMethod(456)); // call protected method
   BOOST_CHECK(protectedValue); // get protected value
   ...
}
BOOST_AUTO_TEST_SUITE_END()

...which is far more concise than writing a subclass as separate from the fixture, which would force you to write all sorts of getters and setters and wrappers for protected members.

in reply to:  2 comment:3 by Tye Z. <tye.zdrojewski@…>, 11 years ago

Sorry, I forgot to add that TestMe extends another class:

class TestMe : public TestMeParent
{
protected:
   bool protectedValue = 0;
   int protectedMethod(int arg) { ... }
   void someProtectedBehavior() { ... }
}

...which is fine. But if the inheritance is virtual, and TestMeParent does not have a default constructor, then its constructor must be specified by every subclass at any level:

class TestMeParent
{
public:
   TestMeParent(int initValue) { ... }
}

class TestMe : public virtual TestMeParent
{
public: 
   TestMe() : 
      TestMeParent(678) // initializer required at every inheritance level
   {
      ... 
   }
}

This breaks my fixture arrangement, because the fixture is subclassed again by the fixture macros.

Hopefully I explained it clearly enough! :)

comment:4 by Gennadiy Rozental, 7 years ago

Resolution: wontfix
Status: newclosed

I am not sure what you recommend us to do in this case. I guess you will have to specialize your base class separately from fixture in this case.

comment:5 by tye.zdrojewski@…, 7 years ago

Resolution: wontfix
Status: closedreopened

The recommendation is right in the original post: "an argument to the FIXTURE macros that would allow the tester to specify some or all of the initialization list".

Is that not do-able for some reason?

comment:6 by Raffi Enficiaud, 5 years ago

Milestone: To Be DeterminedBoost 1.65.0

comment:7 by Raffi Enficiaud, 5 years ago

Owner: changed from Gennadiy Rozental to Raffi Enficiaud
Status: reopenednew

comment:8 by Raffi Enficiaud, 5 years ago

I do not get it: you are writing a fixture for being able to test protected members of TestMeParent, and you do not want to specify the constructions of TestMeParent inside your fixture.

OTOH, having an additional parameter passed to the BOOST_FIXTURE_TEST_SUITE will not help you very far here: you will still need to initialize TestMeParent in some way, and you will still need to forward whatever has been passed to the ctor of TestMe to TestMeParent.

It is a bit confusing, I am flagging this as not doing.

comment:9 by Raffi Enficiaud, 5 years ago

Resolution: wontfix
Status: newclosed

comment:10 by Raffi Enficiaud, 5 years ago

Milestone: Boost 1.65.0To Be Determined

comment:11 by tye.zdrojewski@…, 5 years ago

you do not want to specify the constructions of TestMeParent inside your fixture

...as indicated in the description AND in the example, the virtual parent's init list is "required at every inheritance level". That would include the subclass created by the macro.

We are talking about VIRTUAL inheritance, not regular inheritance.


It is a bit confusing, I am flagging this as not doing.

Please do not close an issue because you are confused.

Note: See TracTickets for help on using tickets.