Ideas for UT needed

Hello,
for my project I use the ideas used on spirit's conjure2 example. Now I
like to do some test with the lexer/grammar using boost::test. The
example uses sequentially initializing all iterators, lexer and grammar.
I like to put this into the fixture but I run into the problem that the
error_handler requires begin/end of iterator.
---8<--- original from conjure2 main
typedef std::string::const_iterator base_iterator_type;
typedef client::lexer::conjure_tokens

[Please do not mail me a copy of your followup] boost-users@lists.boost.org spake the secret code <511BE2CF.9050802@gmx.de> thusly:
My fixture looks so far:
---8<--- typedef std::string::const_iterator base_iterator_type; typedef my_tokens
lexer_type; typedef lexer_type::iterator_type iterator_type; typedef error_handler error_handler_type; struct fixture : private boost::base_from_member
, private boost::base_from_member , my_grammar
"Prefer aggregation over inheritance" for me means that my test fixtures don't derive from the SUT, they have the SUT as a member. In your case, you might want to have the SUT as an auto_ptr so that you can allocate it dynamically during each test case instead of at the time the test case itself is constructed. The auto_ptr (or shared_ptr if you prefer) will destroy the SUT at the end of each test case. Going through all this trouble of using base_from_member just so you can derive from the SUT(s) seems overly complex. But the basic idea is that yes, your test fixture is constructed without arguments, so if you don't know them at the time the fixture is constructed, you provide member functions on your fixture that handle the duplication between test cases with the variation supplied as parameters.
error_handler_base::member requires therefore the iterators first/last. How to give them? In the UT I have further a "test" function object so I can use e.g. it like here:
---8<--- BOOST_FIXTURE_TEST_SUITE(parameter_test, fixture)
BOOST_AUTO_TEST_CASE(my_test) {
BOOST_CHECK(test(rule_to_test, "input to parse", "expected output")); }
I assume here that 'test' is a method on your fixture.
The next problem is related to the original use case. conjure2 is design as a compiler: initialize, analyse, generate and exit - no reuse of the grammar. I like to instance the grammar once (static) and use it several times using the qi::parse function. Since the iterators are fixed, they can't be changed later to point to other sources, isn't it? Is this the right approach for my problem?
I'm not sure I understand this question; are you asking how to unit test your compiler? -- "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

Thank you Richard,
My fixture looks so far:
---8<--- typedef std::string::const_iterator base_iterator_type; typedef my_tokens
lexer_type; typedef lexer_type::iterator_type iterator_type; typedef error_handler error_handler_type; struct fixture : private boost::base_from_member
, private boost::base_from_member , my_grammar "Prefer aggregation over inheritance" for me means that my test fixtures don't derive from the SUT, they have the SUT as a member.
yes, the inheritance approach comes from my understanding (which may be wrong) of the usage of fixture, http://www.boost.org/doc/libs/1_53_0/libs/test/doc/html/utf/user-guide/fixtu.... But it may not exclude aggregation.
But the basic idea is that yes, your test fixture is constructed without arguments, so if you don't know them at the time the fixture is
this is my problem ...
constructed, you provide member functions on your fixture that handle the duplication between test cases with the variation supplied as parameters.
I will check this.
error_handler_base::member requires therefore the iterators first/last. How to give them? In the UT I have further a "test" function object so I can use e.g. it like here:
---8<--- BOOST_FIXTURE_TEST_SUITE(parameter_test, fixture)
BOOST_AUTO_TEST_CASE(my_test) {
BOOST_CHECK(test(rule_to_test, "input to parse", "expected output")); }
I assume here that 'test' is a method on your fixture.
in principle yes, there is a struct test { bool operator(...); }; FO, the fixture provides only the grammar etc. prerequisites.
The next problem is related to the original use case. conjure2 is design as a compiler: initialize, analyse, generate and exit - no reuse of the grammar. I like to instance the grammar once (static) and use it several times using the qi::parse function. Since the iterators are fixed, they can't be changed later to point to other sources, isn't it? Is this the right approach for my problem?
I'm not sure I understand this question; are you asking how to unit test your compiler?
No, my goal is to instance once on demand and use these lexer/grammer etc. to parse more than once different inputs; simply reuse. My UI program is closed by the user, than the main and therefore grammar instance is destroyed. On compilers (like conjure2 example) after eject the code the task is finished and program is closed. If one wish to compile multiple files one executes the compiler binary more than once - each time creating new instances. Hopefully my intentions are more clear. Thanks, Olaf

[Please do not mail me a copy of your followup] boost-users@lists.boost.org spake the secret code <511C9FB4.6090000@gmx.de> thusly:
Thank you Richard,
No problem. If you want more insight into my approach to using Boost.Test for C++, you can read the 5 part series I wrote on my blog: http://legalizeadulthood.wordpress.com/2009/07/04/c-unit-tests-with-boost-te... http://legalizeadulthood.wordpress.com/2009/07/05/c-unit-tests-with-boost-te... http://legalizeadulthood.wordpress.com/2009/07/05/c-unit-tests-with-boost-te... http://legalizeadulthood.wordpress.com/2009/07/05/c-unit-tests-with-boost-te... http://legalizeadulthood.wordpress.com/2009/07/05/c-unit-tests-with-boost-te...
"Prefer aggregation over inheritance" for me means that my test fixtures don't derive from the SUT, they have the SUT as a member.
yes, the inheritance approach comes from my understanding (which may be wrong) of the usage of fixture, http://www.boost.org/doc/libs/1_53_0/libs/test/doc/html/utf/user-guide/fixtu.... But it may not exclude aggregation.
This is referring to the fact that every test case defines a class. The test case class derives from the fixture class. The fixture is just the place where code and data common to multiple tests cases is conveniently located in order to eliminate duplication. While it is certainly possible to have your test fixture derive from the SUT, I would not recommend this as a good practice. Inheritance is the tightest form of coupling that you can have.
But the basic idea is that yes, your test fixture is constructed without arguments, so if you don't know them at the time the fixture is
this is my problem ...
There's nothing that says all your setup has to be in the c'tor of the fixture. You can have the fixture c'tor do basic setup and then provide a method on the fixture that does the variable part. Just have your fixture reference the SUT by auto_ptr<> or shared_ptr<> (so that the fixture d'tor automatically releases the SUT).
I assume here that 'test' is a method on your fixture.
in principle yes, there is a
struct test { bool operator(...); };
If you have this test structure to eliminate duplicated code from test case to test case, then it may be easier to have this code located within the fixture shared between test cases. It would depend on the specific code in question, but if it's a method on the fixture, then it has access to all the data members on the fixture, so you wouldn't need to repeatedly pass them into this test structure in every test case. Here I'm talking about eliminating the duplicated argument lists to test::operator() that would appear in every test case.
I'm not sure I understand this question; are you asking how to unit test your compiler?
No, my goal is to instance once on demand and use these lexer/grammer etc. to parse more than once different inputs; simply reuse. My UI program is closed by the user, than the main and therefore grammar instance is destroyed. On compilers (like conjure2 example) after eject the code the task is finished and program is closed. If one wish to compile multiple files one executes the compiler binary more than once - each time creating new instances. Hopefully my intentions are more clear.
OK, this sounds more like a question of how to organize your lexer/parser combination and how to manage their lifetimes. The Spirit mailing list might be a better place to get an answer to that question. I am a novice Spirit user, but I don't have any specific suggestions or guidance for this. -- "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 (2)
-
legalize+jeeves@mail.xmission.com
-
Olaf Peter