boost/libs/test/example/external_main_example_1.cpp provides an example of a dynamical test suite tree. The invocation of add( BOOST_TEST_CASE(boost::bind(&free_test_function, 1, 1))); results in unpleasant names like "boost::bind( &free_test_function, 1, 2 )" . I used the preprocessor output to override the 2nd arg to make_test_case with a name of my choosing: ts->add(boost::unit_test::make_test_case (boost::unit_test::callback0<> (boost::bind( &free_test_function, 1, 2)), boost::unit_test::const_string( minor, 1))); This works (pretty names and invocable with the logical run_test) but I have no particular confidence that this will survive version changes as well as would BOOST_TEST_CASE. Is there a better way to do this? (stand-alone example attached) -- -ericP office: +1.617.599.3509 mobile: +33.6.80.80.35.59 (eric@w3.org) Feel free to forward this message to any list for any purpose other than email address distribution. There are subtle nuances encoded in font variation and clever layout which can only be seen by printing this message on high-clay paper.
[Please do not mail me a copy of your followup] boost-users@lists.boost.org spake the secret code <20140525080836.GI5022@w3.org> thusly:
boost/libs/test/example/external_main_example_1.cpp provides an example of a dynamical test suite tree. The invocation of add( BOOST_TEST_CASE(boost::bind(&free_test_function, 1, 1))); results in unpleasant names like "boost::bind( &free_test_function, 1, 2 )"
Do you really need to build the test case tree by hand? In your example this could just as easily have been done with BOOST_AUTO_TEST_CASE.
. I used the preprocessor output to override the 2nd arg to make_test_case with a name of my choosing: ts->add(boost::unit_test::make_test_case (boost::unit_test::callback0<> (boost::bind( &free_test_function, 1, 2)), boost::unit_test::const_string( minor, 1)));
This works (pretty names and invocable with the logical run_test) but I have no particular confidence that this will survive version changes as well as would BOOST_TEST_CASE. Is there a better way to do this?
IMO, while passing a functor to BOOST_TEST_CASE works, it was intended to be used with a free function that has an intention-revealing name for the test case. See http://user.xmission.com/~legalize/boost.test/libs/test/doc/html/test/refere... -- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com
* Richard
[Please do not mail me a copy of your followup]
boost-users@lists.boost.org spake the secret code <20140525080836.GI5022@w3.org> thusly:
boost/libs/test/example/external_main_example_1.cpp provides an example of a dynamical test suite tree. The invocation of add( BOOST_TEST_CASE(boost::bind(&free_test_function, 1, 1))); results in unpleasant names like "boost::bind( &free_test_function, 1, 2 )"
Do you really need to build the test case tree by hand?
Generally, yes. I'm working from standard test suites and it makes more sense to read them from the manifest than to write some emacs macro to turn the manifest into procedural code.
In your example this could just as easily have been done with BOOST_AUTO_TEST_CASE.
. I used the preprocessor output to override the 2nd arg to make_test_case with a name of my choosing: ts->add(boost::unit_test::make_test_case (boost::unit_test::callback0<> (boost::bind( &free_test_function, 1, 2)), boost::unit_test::const_string( minor, 1)));
This works (pretty names and invocable with the logical run_test) but I have no particular confidence that this will survive version changes as well as would BOOST_TEST_CASE. Is there a better way to do this?
IMO, while passing a functor to BOOST_TEST_CASE works, it was intended to be used with a free function that has an intention-revealing name for the test case. See http://user.xmission.com/~legalize/boost.test/libs/test/doc/html/test/refere...
That makes sense when you know the intentional names a priori. In my case, I'd have something like std::ifstream man("Manifest.txt"); std::string name, check, expect; int lineNo = 1; while (tsv >> name >> check >> expect) { name = name.substr(1,name.length()-2); check = check.substr(1,check.length()-2); ts->add(BOOST_TEST_CASE (boost::bind(&parseAndCompare, name, check, expect, "Manifest.txt", lineNo))); ++lineNo; } , which results in names that are neither informative nor easy to type as an argument to --run_test. As I alluded to above, I have in the past used a script to rewrite the entries in some manifests as a series of BOOST_AUTO_TEST_CASE( name_with_underbars ) { MY_TEST_MACRO("checkFile1", "expectFile1"); } . This meant that every time someone in the working group proposed adding a test to the manifest, I had to run the script and recompile. With this approach, I can just pull the manifest and run the tests in less than a couple seconds. For this, I incur the danger that the BOOST_TEST_CASE macro may shift underneath me and I'll have to play some catchup.
-- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- -ericP office: +1.617.599.3509 mobile: +33.6.80.80.35.59 (eric@w3.org) Feel free to forward this message to any list for any purpose other than email address distribution. There are subtle nuances encoded in font variation and clever layout which can only be seen by printing this message on high-clay paper.
[Please do not mail me a copy of your followup]
Eric Prud'hommeaux
* Richard
[2014-05-27 19:15+0000] Do you really need to build the test case tree by hand?
Generally, yes. I'm working from standard test suites and it makes more sense to read them from the manifest than to write some emacs macro to turn the manifest into procedural code.
I see.
. I used the preprocessor output to override the 2nd arg to make_test_case with a name of my choosing: ts->add(boost::unit_test::make_test_case (boost::unit_test::callback0<> (boost::bind( &free_test_function, 1, 2)), boost::unit_test::const_string( minor, 1)));
The arguments to boost::unit_test::const_string are the char const* pointer to the string and the number of characters in the string. (For a C style string literal "foo" this is sizeof("foo")-1 which evaluates to 3.) Did you really mean to pass in 1 as the number of characters? boost::unit_test::const_string takes a C-style string literal and provides std::string style compatible semantics (i.e. iterators, length property, etc.). You can think of BOOST_TEST_CASE as just a more convenient way of invoking the constructor for boost::unit_test::test_case: http://user.xmission.com/~legalize/boost.test/libs/test/doc/html/test/refere... I don't see any reason why you couldn't invoke the constructor directly. As for how fragile all of this is -- your guess is as good as mine; I'm not the implementor of the library. -- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com
* Richard
Eric Prud'hommeaux
spake the secret code <20140527203520.GX5022@w3.org> thusly: * Richard
[2014-05-27 19:15+0000] Do you really need to build the test case tree by hand?
Generally, yes. I'm working from standard test suites and it makes more sense to read them from the manifest than to write some emacs macro to turn the manifest into procedural code.
I see.
. I used the preprocessor output to override the 2nd arg to make_test_case with a name of my choosing: ts->add(boost::unit_test::make_test_case (boost::unit_test::callback0<> (boost::bind( &free_test_function, 1, 2)), boost::unit_test::const_string( minor, 1)));
The arguments to boost::unit_test::const_string are the char const* pointer to the string and the number of characters in the string. (For a C style string literal "foo" this is sizeof("foo")-1 which evaluates to 3.)
Did you really mean to pass in 1 as the number of characters?
Yes, but just because my original attached example had trivial names constructed by crossing the chars in argv[1] and argv[2], e.g. abc 12 -> a1 b1 c1 a2 b2 c2.
boost::unit_test::const_string takes a C-style string literal and provides std::string style compatible semantics (i.e. iterators, length property, etc.).
You can think of BOOST_TEST_CASE as just a more convenient way of invoking the constructor for boost::unit_test::test_case: http://user.xmission.com/~legalize/boost.test/libs/test/doc/html/test/refere...
I don't see any reason why you couldn't invoke the constructor directly.
That makes sense. I wonder why the macros invoke make_test_cast, which then invokes the constructor: from boost/test/unit_test_suite_impl.hpp:252: inline test_case* make_test_case( callback0<> const& test_func, const_string tc_name ) { return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func ); } , maybe some mechanical constraints on invoking constructors from macros? In case anyone's following along now or in the future, the example posted at the head of this thread works with the test_case constructor invoked directly (note swapped order of args): using make_test_case: ts->add(boost::unit_test::make_test_case (boost::unit_test::callback0<> (boost::bind( &free_test_function, 1, 2)), boost::unit_test::const_string( minor, 1))); constructing test_case directly: ts->add(new boost::unit_test::test_case (boost::unit_test::const_string( minor, 1), boost::unit_test::callback0<> (boost::bind( &free_test_function, 1, 2)))); Thanks, Richard!
As for how fragile all of this is -- your guess is as good as mine; I'm not the implementor of the library. -- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- -ericP office: +1.617.599.3509 mobile: +33.6.80.80.35.59 (eric@w3.org) Feel free to forward this message to any list for any purpose other than email address distribution. There are subtle nuances encoded in font variation and clever layout which can only be seen by printing this message on high-clay paper.
[Please do not mail me a copy of your followup]
Eric Prud'hommeaux
* Richard
[2014-05-27 23:20+0000] Did you really mean to pass in 1 as the number of characters?
Yes, but just because my original attached example had trivial names constructed by crossing the chars in argv[1] and argv[2], e.g. abc 12 -> a1 b1 c1 a2 b2 c2.
In this case the number of characters in the test names are 2 :-)
That makes sense. I wonder why the macros invoke make_test_cast, which then invokes the constructor:
from boost/test/unit_test_suite_impl.hpp:252: inline test_case* make_test_case( callback0<> const& test_func, const_string tc_name ) { return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func ); } , maybe some mechanical constraints on invoking constructors from macros?
No, it is just so that they can call normalize_test_case_name which strips the leading '&' from any name, so if you did BOOST_TEST_CASE(&fn), the test case name would be 'fn', not '&fn'. -- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com
* Richard
Eric Prud'hommeaux
spake the secret code <20140528082105.GB29665@w3.org> thusly: * Richard
[2014-05-27 23:20+0000] Did you really mean to pass in 1 as the number of characters?
Yes, but just because my original attached example had trivial names constructed by crossing the chars in argv[1] and argv[2], e.g. abc 12 -> a1 b1 c1 a2 b2 c2.
oops, should have written that as a/1 b/1 c/1 a/2 b/2 c/2, which gives the highly informative names "1" and "2" as test case names. This brings up a feature request (or maybe I just didn't find it) which would be that the error reports look like: filename(num): error in test "a/1" Currently, it only includes the test name ("1" in this case) but I think the suite hierarcy would be very helpful for folks who see an error and need to frob up a --run_test=a/1 to run it again in a debugger.
In this case the number of characters in the test names are 2 :-)
That makes sense. I wonder why the macros invoke make_test_cast, which then invokes the constructor:
from boost/test/unit_test_suite_impl.hpp:252: inline test_case* make_test_case( callback0<> const& test_func, const_string tc_name ) { return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func ); } , maybe some mechanical constraints on invoking constructors from macros?
No, it is just so that they can call normalize_test_case_name which strips the leading '&' from any name, so if you did BOOST_TEST_CASE(&fn), the test case name would be 'fn', not '&fn'. -- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- -ericP office: +1.617.599.3509 mobile: +33.6.80.80.35.59 (eric@w3.org) Feel free to forward this message to any list for any purpose other than email address distribution. There are subtle nuances encoded in font variation and clever layout which can only be seen by printing this message on high-clay paper.
Eric Prud'hommeaux
This brings up a feature request (or maybe I just didn't find it) which would be that the error reports look like: filename(num): error in test "a/1" Currently, it only includes the test name ("1" in this case) but I think the suite hierarcy would be very helpful for folks who see an error and need to frob up a --run_test=a/1 to run it again in a debugger.
You can use --log_level=test_suite And you'll see all the test units being entered. Otherwise feel free to file a new feature request. Gennadiy
[Please do not mail me a copy of your followup]
Eric Prud'hommeaux
This brings up a feature request (or maybe I just didn't find it) which would be that the error reports look like: filename(num): error in test "a/1" Currently, it only includes the test name ("1" in this case) but I think the suite hierarcy would be very helpful for folks who see an error and need to frob up a --run_test=a/1 to run it again in a debugger.
Yeah, I've been wanting this as well. -- "The Direct3D Graphics Pipeline" free book http://tinyurl.com/d3d-pipeline The Computer Graphics Museum http://computergraphicsmuseum.org The Terminals Wiki http://terminals.classiccmp.org Legalize Adulthood! (my blog) http://legalizeadulthood.wordpress.com
participants (3)
-
Eric Prud'hommeaux
-
Gennadiy Rozental
-
legalize+jeeves@mail.xmission.com