Le 2010-07-17 à 1:07, Walter Bright a écrit :

> Yes, but it's not hard. For me, the issue is making things for the user
> more complicated. D is already a very large language, and adding more
> and more stuff like this makes it larger, buggier, and less
> approachable. For example, nothing stands out to say what "unittest
> assert" does vs "assert".

I just want to point out that "unittest assert(x);" would just be a shortcut 
for "unittest { assert(x); }", which is quite similar to how you can omit the 
braces for conditional and loop statements in regular code. This is only a 
small shift from the earlier concept of unittest in D: instead of having 
unittest blocks scattered in your module, you have unittest statements (which 
can be blocks) scattered around. It's not much of a change, it's just being 
more permissive.

        module abc;

        unittest assert(sqrt(4) == 2); // single-statement unit test
        unittest assert(sqrt(16) == 4);

As for nesting unittests, I agree that it might get harder to conceptualize how 
it works. But still, there isn't anything really 'special' about it, they have 
the same semantics as the module-level ones. It's better explained with a 
concrete example. Say a module includes those unit tests:

        module abc;

        unittest assert(sqrt(4) == 2);
        unittest assert(sqrt(16) == 4);

        unittest {
                int[] result = makeSomeTable(399, 383, 927);
                assert(result.length == 3); // guard against invalid state

                unittest assert(result[0] == 281);
                unittest assert(result[1] == 284);
                unittest assert(result[2] == 283);

                unittest {
                        int[] derivedResult = derive(result);
                        assert(derivedResult.length == 2); // guard against 
invalid state

                        unittest assert(derivedResult[0] ==  3);
                        unittest assert(derivedResult[1] == -1);
                }
                // ... other tests reusing 'result'
        }

How do you translate this to a module-level unittest function? First define 
this function in the runtime:

        void __doUnitTest(void delegate() test) {
                try { test(); }
                catch (AssertionError e) { __unitTestLogFailure(e); }
        }

Then replace each unittest statement or block with a call to the above 
function, passing the unittest code as the argument. The three module-level 
unittests I wrote above would translate to this module unittest function:

        void __module_abc_unittests() {
                __doUnitTest({  assert(sqrt(4) == 2); });
                __doUnitTest({  assert(sqrt(16) == 4); });

                __doUnitTest({
                        int[] result = makeSomeTable(399, 383, 927);
                        assert(result.length == 3); // guard against invalid 
state
        
                        __doUnitTest({  assert(result[0] == 281);  });
                        __doUnitTest({  assert(result[1] == 284);  });
                        __doUnitTest({  assert(result[2] == 283);  });

                        __doUnitTest({
                                int[] derivedResult = derive(result);
                                assert(derivedResult.length == 2); // guard 
against invalid state

                                __doUnitTest({  assert(derivedResult[0] ==  3); 
 });
                                __doUnitTest({  assert(derivedResult[1] == -1); 
 });
                        });
                        // ... other tests reusing 'result'
                });
        }

As other mentioned, what I do here with nested unit tests could easily be 
implemented by offering the user a new library function too. I just happen to 
think what I'm proposing here is more elegant.

-- 
Michel Fortin
[email protected]
http://michelf.com/



_______________________________________________
phobos mailing list
[email protected]
http://lists.puremagic.com/mailman/listinfo/phobos

Reply via email to