Kim Gr=E4sman wrote:
> I actually tried to come up with Abstract Test in UT++ yesterday. I never
> managed. I don't think it can be done (famous last words) without some
> pretty decent additions to the macro family.
As I suspected, that's a hardship of the existing architecture.
Could the SUITE() macro upgrade to support it?
My parallel-evolved TEST_() macro supports it like this. It works like
UnitTest++'s TEST_FIXTURE(), and it needs a tweak to support Abstract
Tests. So suppose we have a dialog box that localizes to Sanskrit, and
we need to test English and all the other languages. First we switch
our latest test, _checkAllLabels, to constrain English instead of
Sanskrit, and we extract from the fixture TestSanskrit a base class
called TestDialog. This refactor moves the case we will abstract up
the inheritance graph:
TEST_(TestDialog, _checkAllLabels)
{
// stuff here to find each string in the dialog, check its
// locale is correct, check it contains no MISSING CHARACTER
// GLYPHs [], check it doesn't overflow the dialog, etc
}
Now write a new macro that reuses a test case, such as
_checkAllLabels, into any derived suite, using some good old-fashioned
"Diamond Inheritance":
#define TEST_(suite, target) \
struct suite##target: virtual suite \
{ void runCase(); } \
a##suite##target; \
void suite##target::runCase()
#define RETEST_(base, suite, target) \
struct base##suite##target: \
virtual suite, \
virtual base##target { \
void setUp() { suite::setUp(); } \
void runCase() { base##target::runCase(); } \
void tearDown() { suite::tearDown(); } \
} a##base##suite##target;
=85
Then express that macro with three parameters: The base class, the
derived class whose setUp() and tearDown() we need, and one base class
case. The macro reuses that case with the derived class:
RETEST_(TestDialog, TestSanskrit, _checkAllLabels)
That change required TestSanskrit to inherit TestDialog virtually, to
ensure that suite::setUp() sets up the same m_aDlg member object as
base##target::runCase() tests.
Without virtual inheritance, C++'s multiple inheritance system would
make a UML diagram of our design into a huge V, disconnected at the
top. The TestDialogTestSanskrit_checkAllLabels object would contain
two different TestDialog sub-objects, and these would disagree which
instance of their member variable m_aDlg to test, and which to
localize to Sanskrit.
Future extensions could create a template that abstracts setUp() and
tearDown() across a list of locales. When the time comes to conquer -
oops I mean "support" - the entire world, we should build more
elaborate Abstract Tests, then declare stacks of them, one per target
locale:
RETEST_(TestDialog, TestLocale< LANG_AFRIKAANS >,_checkAllLabels)
RETEST_(TestDialog, TestLocale< LANG_ALBANIAN >,_checkAllLabels)
RETEST_(TestDialog, TestLocale< LANG_ARABIC >,_checkAllLabels)
RETEST_(TestDialog, TestLocale< LANG_ARMENIAN >,_checkAllLabels)
RETEST_(TestDialog, TestLocale< LANG_ASSAMESE >,_checkAllLabels)
RETEST_(TestDialog, TestLocale< LANG_AZERI >,_checkAllLabels)
RETEST_(TestDialog, TestLocale< LANG_BASQUE >,_checkAllLabels)
=85
Their test cases should sweep each window and control, for each
locale. We can add things like a spelling and grammar checker to only
one place in the code.
--=20
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!
|