Boost logo

Boost Users :

Subject: Re: [Boost-users] [test] Init framework before dataset generation
From: Florian Lindner (mailinglists_at_[hidden])
Date: 2016-09-16 03:31:17


Am 28.08.2016 um 17:00 schrieb Raffi Enficiaud:
> Le 24/08/16 à 13:04, Florian Lindner a écrit :
>> Hello,
>>
>> I try to use boost test with data test cases:
>>
>> std::vector<float> fibonacci() {
>> std::cout << "Data Set" << std::endl;
>> [...]
>> }
>>
>> BOOST_DATA_TEST_CASE(datatest, boost::unit_test::data::make(fibonacci()), mapping)
>> {
>> std::cout << "Datatype" << typeid(mapping).name() << std::endl;
>> }
>>
>> The problem of that is, that fibonacci is initialized before anything else. The order of initializations is:
>>
>> Data Set
>> main
>> init_unit_test
>> Global Fixture
>>
>> That works fine here, but my fibonacci uses MPI which needs to initialized by MPI_Init. I want to do that
>> initialization in the global fixture or int main or init_unit_tests, once for the entire test runner.
>>
>> Is there anything I can do about that and belay initialization of Data Set after one of the others?
>>
>> Thanks,
>> Florian
>>
>
> The macro BOOST_DATA_TEST_CASE is expanded at compilation time, and the object passed to it (the dataset) is then
> evaluated before main.
>
> However, you can define your own dataset. In the case of the Fibonacci, there is an example [1] that is quite simple here:
>
> https://github.com/boostorg/test/blob/develop/doc/examples/dataset_example68.run-fail.cpp
>
> I am not 100% sure, but I believe that your need can be adapted to this interface.
>
> Let me know if this helps, and if it doesn't, please open a ticket/feature request on trac (https://svn.boost.org/trac/).
>
> Raffi
>
>
> [1] Apparently this example was /inadvertently/ removed from the doc, I am resurrecting it as well as the definition of
> a dataset interface.

Hey,

thanks your input! I'm still struggling to get it working, so that the test case is not evaluated before the test is
about to run. My code now looks like that:

// ----------------------------------------------------------------------

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/data/monomorphic.hpp>

#include <iostream>
#include <string>
using namespace std;

struct Test : public std::string { // derive from string to get operator<< that boost requires
  Test() { cout << "Test is instantiated." << endl; }
};

namespace bdata = boost::unit_test::data;

template <class T>
class RuntimeDataset {
public:

  using sample = typename T::value_type;;
  enum { arity = 1 };

  T data;

  explicit RuntimeDataset(T _data) {
    cout << "Init dataset" << endl;
    data = _data;
  }

  bdata::size_t size() const {
    return data.size();
  }

  typename T::const_iterator begin() const {
    return data.cbegin();
  }
};

namespace boost { namespace unit_test { namespace data { namespace monomorphic {
template <class T>
struct is_dataset<RuntimeDataset<T>> : boost::mpl::true_ {};
}}}}

struct Fixture {
  Fixture() {
    cout << "Fixture" << endl;
  }
};

BOOST_AUTO_TEST_SUITE(MySuite)

BOOST_DATA_TEST_CASE_F(
  Fixture,
  test1,
  RuntimeDataset<std::vector<Test>>( { Test() } ), // This should be evaluated when the test is about to run
  input)
{
  BOOST_TEST(true);
}

BOOST_AUTO_TEST_SUITE_END()

// ----------------------------------------------------------------------

Test is still initialized at the very beginning, and yes, it's obviously correct, but not what I want ;-)

I could probably hard code the list into the iterator of RuntimeDataset. (Is that what you suggested?). But then I need
to implement a class for each data driven test.

Any more suggestions?

Best,
Florian


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net