Thread overview
[Issue 13291] unittest should be allowed inside template functions
Aug 14, 2014
timon.gehr@gmx.ch
Aug 14, 2014
Walter Bright
Aug 14, 2014
timon.gehr@gmx.ch
Aug 14, 2014
timon.gehr@gmx.ch
Sep 16, 2014
Sobirari Muhomori
August 14, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

timon.gehr@gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr@gmx.ch

--- Comment #1 from timon.gehr@gmx.ch ---
(In reply to Andrei Alexandrescu from comment #0)
> there's no way to instantiate and fire a unittest for each instantiation of a function template.

This is actually not true (also pointed out by Meta on the forum):

template fun(T){
    void fun(T arg){
        ... stuff ...
    }
    unittest{
        ... unittest for each T instantiated ...
    }
}

I.e. this enhancement suggests a shorthand syntax.

--
August 14, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com
           Hardware|x86                         |All

--- Comment #2 from Walter Bright <bugzilla@digitalmars.com> ---
(In reply to timon.gehr from comment #1)
> I.e. this enhancement suggests a shorthand syntax.

And it suggests a "lowering" method of implementing it that is just a rewrite.

--
August 14, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

--- Comment #3 from Andrei Alexandrescu <andrei@erdani.com> ---
Honest I did think of the template/eponymous trick but was too lazy to open it for discussion... there would be issues of overloading etc. left to solve with that one.

--
August 14, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

--- Comment #4 from timon.gehr@gmx.ch ---
(In reply to Andrei Alexandrescu from comment #3)
> Honest I did think of the template/eponymous trick but was too lazy to open it for discussion... there would be issues of overloading etc. left to solve with that one.

What are those issues?

--
August 14, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

--- Comment #5 from Andrei Alexandrescu <andrei@erdani.com> ---
(In reply to timon.gehr from comment #4)
> (In reply to Andrei Alexandrescu from comment #3)
> > Honest I did think of the template/eponymous trick but was too lazy to open it for discussion... there would be issues of overloading etc. left to solve with that one.
> 
> What are those issues?

I'm thinking of (a) putting two or more overloads inside the same template -
then the unittest can't distinguish which is being instantiated (arguably that
could be considered a mistaken us); (b) would overloading a template with a
generic function just work?

template fun(T) { void fun(T, int); }
void fun(T)(T, double);

Tried this, does work. I wonder if it works for all overloading cases.

--
August 14, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

--- Comment #6 from timon.gehr@gmx.ch ---
(In reply to Andrei Alexandrescu from comment #5)
> (In reply to timon.gehr from comment #4)
> > (In reply to Andrei Alexandrescu from comment #3)
> > > Honest I did think of the template/eponymous trick but was too lazy to open it for discussion... there would be issues of overloading etc. left to solve with that one.
> > 
> > What are those issues?
> 
> I'm thinking of (a) putting two or more overloads inside the same template -
> then the unittest can't distinguish which is being instantiated (arguably
> that could be considered a mistaken us);

(The new syntax does not allow this.)

> (b) would overloading a template
> with a generic function just work?
> 
> template fun(T) { void fun(T, int); }
> void fun(T)(T, double);
> 
> Tried this, does work. I wonder if it works for all overloading cases.

There is no case where e.g.

void foo(T)(T arg){ ... }

behaves differently from e.g.

template foo(T){ void foo(T arg){ ... } }

The former is lowered to the latter (DMD does this in the parser AFAIK).

The way to implement the new syntax would be to simply lower it to something of the form of the example in comment #1.

--
September 16, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

Steven Schveighoffer <schveiguy@yahoo.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |schveiguy@yahoo.com

--- Comment #7 from Steven Schveighoffer <schveiguy@yahoo.com> ---
Using the template instantiation to cover all unit tests is both a boon and a curse.

I use it in dcollections to great effect, and have found several D/phobos bugs just with that use.

However, often you do NOT want to instantiate unit tests for ALL invocations.

Consider this:

T max(T)(T x, T y)

A test for max might look like:

unittest
{
   T t1 = 0, t2 = 1, t3 = 2;
   assert(max(t1, t2) == t2);
   assert(max(t2, t1) == 1);
   assert(max(t1, t3) == t3);
   assert(max(t3, t2) == 2);

   // etc...
}

But what if T is string?

Now, you have to create a different unit test because the literals are different. Unit tests require both input and results, and the input isn't always easy to determine for any generic type.

--
September 16, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

Sobirari Muhomori <dfj1esp02@sneakemail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=13454

--- Comment #8 from Sobirari Muhomori <dfj1esp02@sneakemail.com> ---
Related: issue 13454

--
December 18, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

Andrei Alexandrescu <andrei@erdani.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |INVALID

--- Comment #9 from Andrei Alexandrescu <andrei@erdani.com> ---
I just realized this can be realized with relative ease as follows:

void fun(T)(T arg)
{
   version(unittest)
   {
      ... testing ...
   }
   ... stuff ...
}

To avoid running unittests every time:

void fun(T)(T arg)
{
   version(unittest) for (static bool tested; !tested; tested = true)
   {
      ... testing stuff ...
   }
   ... stuff ...
}

--
December 18, 2014
https://issues.dlang.org/show_bug.cgi?id=13291

--- Comment #10 from Steven Schveighoffer <schveiguy@yahoo.com> ---
(In reply to Andrei Alexandrescu from comment #9)
> I just realized this can be realized with relative ease as follows:
> 
> void fun(T)(T arg)
> {
>    version(unittest)
>    {
>       ... testing ...
>    }
>    ... stuff ...
> }

That won't run during unit tests, though. But I think Timon's point covers the request.

--