August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 08/14/2014 08:26 PM, bearophile wrote:
> Andrei Alexandrescu:
>> Destroy https://issues.dlang.org/show_bug.cgi?id=13291?
>
> I'd like a way to test nested functions:
>
>
> void foo() {
> int bar() { return 0; }
>
> unittest {
> assert(bar() == 1);
> }
> }
>
> void main() {}
>
>
> Bye,
> bearophile
It is already possible, but I doubt that this is intended (where would the unit test get the enclosing stack frame of 'foo' from?):
void foo(){
int bar(){ return 0; }
mixin barTest;
}
template barTest(){
unittest {
assert(bar()==1);
}
}
void main() {}
You should be safe for static nested functions though, which the compiler will enforce are the only ones called if you make the unit test 'static'. :o)
| |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Timon Gehr | On 08/14/2014 08:39 PM, Timon Gehr wrote:
> On 08/14/2014 08:26 PM, bearophile wrote:
>> Andrei Alexandrescu:
>>> Destroy https://issues.dlang.org/show_bug.cgi?id=13291?
>>
>> I'd like a way to test nested functions:
>> ...
>> void foo() {
>> int bar() { return 0; }
>>
>> unittest {
>> assert(bar() == 1);
>> }
>> }
>>
>> void main() {}
>> ...
> It is already possible, ...
Another way:
void foo(){
static int bar() { return 0; }
static struct T{ unittest{ assert(bar()==1); } }
}
void main() {}
| |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Thursday, 14 August 2014 at 18:26:06 UTC, bearophile wrote:
> Andrei Alexandrescu:
>> Destroy https://issues.dlang.org/show_bug.cgi?id=13291?
>
> I'd like a way to test nested functions:
>
>
> void foo() {
> int bar() { return 0; }
>
> unittest {
> assert(bar() == 1);
> }
> }
>
> void main() {}
>
>
> Bye,
> bearophile
Nested functions are not really "units" - they are implementation details.
| |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Thu, Aug 14, 2014 at 06:26:05PM +0000, bearophile via Digitalmars-d wrote: > Andrei Alexandrescu: > >Destroy https://issues.dlang.org/show_bug.cgi?id=13291? > > I'd like a way to test nested functions: > > > void foo() { > int bar() { return 0; } > > unittest { > assert(bar() == 1); > } > } > > void main() {} [...] When should such unittests be run, and how should the following code behave? void foo(int x) { int bar() { return x+1; } unittest { // When is this unittest run? What's the value // of x when the unittest runs? assert(bar() == 1); } } T -- "Uhh, I'm still not here." -- KD, while "away" on ICQ. | |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Thursday, 14 August 2014 at 04:04:11 UTC, H. S. Teoh via Digitalmars-d wrote: > On Wed, Aug 13, 2014 at 06:10:54PM -0700, Andrei Alexandrescu via Digitalmars-d wrote: >> Destroy https://issues.dlang.org/show_bug.cgi?id=13291? > [...] > > 1) How to add attributes to the unittest without them clashing with the > function's attributes? It probably couldn't have any. > 2) How to parse ddoc comments for the unittest? I wouldn't expect it to make any sense to use a unittest block like that for documentation. The documentation examples are going to need specific types. It needs to be possible to actually try out the examples. > 3) Where should unittest block stand in relation to in/out contracts? Does it matter? I don't know what the current grammar says with regards to in and out - maybe it requires that in be before out - but I don't see any real reason to care about the order. Why not just let them be in any order as long as the body is last? > 4) How much can you realistically test on a generic type argument T, > that you can't already cover with concrete types? I'm finding that the > per-instantiation behaviour of unittest blocks inside templated > structs/classes is rarely desired, esp. when you write ddoc unittests > (because you want code examples in the docs to involve concrete types, > not abstract types, otherwise they are of limited use to the reader). > Because of this, I often move unittests outside the aggregate or enclose > them in static if's. This suggests that perhaps per-instantiation > unittests are only of limited utility. I have _rarely_ found it to be useful to write generic tests inside of a template. It's a cute thing to be able to do and occasionally useful, but for the most part, I find it to be very annoying. For a templated function, it's not that big a deal, but for tremplated types, it's a nightmare. You're forced to put all of your unittest blocks outside of the struct or class, and you can't really use ddoc-ed unittest blocks. I'd actually prefer that the unittest blocks _didn't_ get generated for each instantation, but I think that that ship has unfortunately sailed, and it could be a bit of an implementation problem to have them not really be part of the template even though they're in it. But aside from whether it's desirable for unittest blocks to be instantiated with the template or not, generating tests that way rarely makes much sense in my experience. Simple things like constructing the types involved and checking them agains the desired result just don't work, because you can't generically construct values of a type. Do you want [1, 2, 3, 4, 5], or ["hello", "world", "goodbye"]? Those types invariably depend on what the template was instiated with, making the genericity not work for the tests. I'm not necessarily against adding the proposed feature to the language, but it's just shorthand to avoid splitting out the template from the function, and I doubt that I'd ever use it. - Jonathan M Davis | |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Meta | On Thursday, 14 August 2014 at 05:53:43 UTC, Meta wrote:
> On Thursday, 14 August 2014 at 01:10:54 UTC, Andrei Alexandrescu wrote:
>> Destroy https://issues.dlang.org/show_bug.cgi?id=13291?
>>
>> Andrei
>
> It's worth noting that you can currently do this:
>
> template fun(T)
> {
> int fun(T val)
> {
> static if(is(T == string) || is(T == float))
> {
> return 0;
> }
> else
> {
> return 1;
> }
> }
>
> unittest
> {
> assert(fun(T.init) == 0);
> }
> }
>
> void main()
> {
> fun("test"); //Ok
> fun(3.0f); //Ok
> fun(1); //AssertError thrown
> }
Yeah. This proposal adds a shortcut to do this sort of thing, but it doesn't actually add new functionality. And in my experience, it's not even useful functionality. It's just too hard to be able to generic types, because construction isn't generic. _Some_ things can be tested generically (particularly if all you need is the init value for a type), and it's occasionally useful, but in most cases, it isn't. So, I don't think that it really hurts to add this feature, but I don't think that it really adds much either.
- Jonathan M Davis
| |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Chris Cain | On 8/13/2014 7:54 PM, Chris Cain wrote:
> Current behavior is 1. So it'd be really necessary to come up with some new,
> unambiguous syntax to put the unittest after the function. Whereas the current
> proposal doesn't create an ambiguity and doesn't need new, special syntax to
> perform this task.
That's a good and insightful point.
| |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 8/13/2014 9:02 PM, H. S. Teoh via Digitalmars-d wrote:
> 4) How much can you realistically test on a generic type argument T,
> that you can't already cover with concrete types? I'm finding that the
> per-instantiation behaviour of unittest blocks inside templated
> structs/classes is rarely desired, esp. when you write ddoc unittests
> (because you want code examples in the docs to involve concrete types,
> not abstract types, otherwise they are of limited use to the reader).
> Because of this, I often move unittests outside the aggregate or enclose
> them in static if's. This suggests that perhaps per-instantiation
> unittests are only of limited utility.
Just to expand on this, one of the great advantages of template functions and separate unittests is the unittest can instantiate the template function with "mocked up" arguments. Instantiating the unittest for every type passed to it would defeat that method.
| |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | Idan Arye: > Nested functions are not really "units" - they are implementation details. It's not important how you call them. I'd still like some nice way to test those "details" :-) ---------------- H. S. Teoh: > When should such unittests be run, and how should the following code behave? Is just after the post-condition of the enclosing function a good moment to run them? Bye, bearophile | |||
August 14, 2014 Re: unittesting generic functions | ||||
|---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Thu, Aug 14, 2014 at 08:38:31PM +0000, bearophile via Digitalmars-d wrote: [...] > H. S. Teoh: > > >When should such unittests be run, and how should the following code behave? > > Is just after the post-condition of the enclosing function a good moment to run them? [...] So you're suggesting that these unittests should run at *every single function call*? That sounds like total overkill to me. Furthermore, if the unittest fails, what should the runtime do, now that the program is actually already running? Aborting seems to be the most reasonable answer, in which case the question is, why not just write asserts in the outer function instead? T -- Skill without imagination is craftsmanship and gives us many useful objects such as wickerwork picnic baskets. Imagination without skill gives us modern art. -- Tom Stoppard | |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply