Liskov principle and unittest
Philippe Sigaud
philippe.sigaud at gmail.com
Mon Sep 26 12:23:00 PDT 2011
On Mon, Sep 26, 2011 at 14:05, deadalnix <deadalnix at gmail.com> wrote:
>> The limitation is I'm not sure that would work for class templates
>> hierarchies.
>
> Sounds nice ! I'm pretty sure this has some limitations, but that
> definitively a step forward.
>
> I'll do some tests about that.
>
> If the getDerived isn't devellopped, then the whole stuff will fail at
> compile time, so this ok. We can be sure that tests are performed for every
> derived classes, and so, even if the devellopper of the derived class forgot
> to do unittest or don't want to.
Here is the missing code:
/** finds all local (module-level) classes */
template LocalClasses()
{
mixin("alias TypeTuple!" ~ localClasses() ~ " LocalClasses;");
}
string localClasses()
{
string result;
foreach(i, symbol;mixin("__traits(allMembers, " ~ .stringof[7..$] ~ ")"))
mixin("static if (is(" ~ symbol ~ " == class))
result ~= symbol ~ \",\";");
return "(" ~ result[0..$-1] ~ ")";
}
/** Given a class type, returns the local (module-level)
children classes. */
template GetDerived(Type) if (is(Type == class))
{
mixin("alias TypeTuple!(" ~ getDerivedFrom!Type ~ ") GetDerived;");
}
string getDerivedFrom(Type)() if (is(Type == class))
{
string result;
foreach(i, Class; LocalClasses!())
static if (is(Class : Type))
result ~= Class.stringof ~ ",";
return result;
}
string testDerived(Origin, alias generator)() if (is(Origin == class))
{
alias GetDerived!Origin Children;
string result;
foreach(i, Child; Children)
result ~= "unittest\n{\n" ~ generator!Child ~ "\n}\n";
return result;
}
/** Stub unit-test, just generating a pragma(msg, ...) call */
string genUT(Type)()
{
return "pragma(msg, \"testing for \", " ~ Type.stringof ~ ");";
}
// Usage:
class C1 {}
class C2 {}
class C3: C2 {}
class C4 : C2 {}
class C5 : C4 {}
mixin(testDerived!(C2, genUT));
This will find that C2 derived classes are C3, C4 and C5 and will
generate stub unit-tests for each of them. Not for C1, because it's
not derived from C2.
Hey, I even found a way to statically reconstitute the entire class
tree. It feels good to code in D again!
Limitations :
- not tested with multi-modules hierarchies. I know how to get the
module (not package) imports from a module name, so I could recurse on
them. But packages are problematic.
- class templates may cause problems.
More information about the Digitalmars-d
mailing list