Re: unittest blocks not being run inside of class and struct templates

2017-07-27 Thread Jonathan M Davis via Digitalmars-d-learn
On Tuesday, July 25, 2017 09:31:28 Steven Schveighoffer via Digitalmars-d-
learn wrote:
> The unfortunate thing is that if you want to have non-templated unit
> tests, you have to put them outside the struct itself. This sucks for
> documented unit tests, and for tests being close to the thing being
> tested. I'd love to have a way to specify that a unit test is really
> outside the struct, but still have it written inside. I'm not sure if it
> would be accepted though.

When there was a discussion that previously (earlier this year, I think), I
was talking about updating the DIP on this that I'd created, and Andrei
basically said that it was a waste of my time to do so and that it would be
rejected. I don't know what Walter's position on it is (though previous
discussions on the topic imply that Walter doesn't think that the issue is a
big deal), and I don't know what it would take to talk Andrei into it, but I
expect that it would require a _very_ well written DIP with very good
reasons as to why a language feature was better than the pain of doing
something like you did with RedBlackTree. But Andrei certainly seemed to
think that doing what you did with RedBlackTree was perfectly acceptable as
opposed to disgustingly ugly, albeit better than just letting the tests sit
there and get compiled into every instantiation.

The DIP I wrote previously suggested using static on the unittest blocks to
indicate that they weren't really part of the template, which seemed
perfectly reasonable to me, but Timon had a decent argument as to why
reusing static didn't make sense. So, we'd need some other sort of attribute
to do it, but regardless, IMHO having an attribute of some kind to solve
this problem would be light years better than what we have now.
Unfortunately, previous discussions on the topic indicate that any DIP on
the subject is likely to get rejected, which pisses me off given how ugly
the workaround is, but I don't know what to do about it except maybe wait
awhile before creating the DIP in the hopes that putting some time between
the DIP being proposed and Andrei basically saying that any such DIP would
be rejected would make it less likely that he'd remember that and more
likely that he'd be receptive to it. However, without something more that
shows that it's a serious problem, I question that we stand much chance of
convincing him. But maybe I just suck at explaining why this issue is bad
enough to merit a language fix and someone else could explain it in a way
that would convince him.

- Jonathan M Davis



Re: unittest blocks not being run inside of class and struct templates

2017-07-25 Thread Kagamin via Digitalmars-d-learn

On Tuesday, 25 July 2017 at 02:48:57 UTC, NoBigDeal256 wrote:
What is the standard way of testing class templates in the 
context of a library where some of the classes may never 
actually be used by the library itself?


Write a test and instantiate whatever templates you want to test.

class Test(T) {
}

unittest {
auto t=new Test!int;
assert(t.method1()==1);
}


Re: unittest blocks not being run inside of class and struct templates

2017-07-25 Thread Steven Schveighoffer via Digitalmars-d-learn

On 7/24/17 11:13 PM, NoBigDeal256 wrote:

On Tuesday, 25 July 2017 at 02:18:41 UTC, Adam D. Ruppe wrote:

On Tuesday, 25 July 2017 at 02:11:20 UTC, NoBigDeal256 wrote:
it passes when it should fail because the unittest block is never 
executed. Why is this?


Did you actually instantiate the class somewhere? A template has no 
concrete code unless created with an argument somewhere...


What if it's instantiated in another module? Right now I'm having issues 
where if I run 'dmd a.d b.d -unittest' and the class template in b.d is 
instantiated in a.d and it compiles and the tests inside my class 
template run as they should, but when using 'dub test' the tests in my 
class template don't run at all as if it isn't instantiated in a.d even 
though it is. This is the original issue that I had that prompted me to 
create this thread.


There is a whole can of worms to be dealt with if you put unit tests 
inside template classes or structs.


For instance:

struct Foo(T)
{
   T foo() { return T.init; }
   unittest
   {
   Foo!int f;
   assert(is(typeof(f.foo()) == int));
   }
}

the unit test is instantiated EVERY TIME Foo is instantiated, so if you 
have Foo!int and Foo!string both instantiated, BOTH will run this unit 
test. Obviously, there is no need to run both. And yes, user code will 
also add unit tests unwittingly to their code.


In some cases, this can be useful. If you write like this:

struct Foo(T)
{
   T foo() { return T.init; }
   unittest
   {
   Foo f; // note the lack of !
   assert(is(typeof(f.foo()) == T));
   }
}

This means that for every instantiation, the unit test is checking that 
Foo.foo returns T.


But this comes at a cost. Generally unit tests deal with concrete data, 
not abstract concepts. This means, you really only want to unit test for 
some instantiations, not all.


In phobos, I did this for RedBlackTree. It works well, in that test 
coverage is nearly complete over all integral types of elements. 
However, there are drawbacks:


1. RedBlackTree with -unittest *will* add unit tests to user modules 
(unavoidable).

2. There are some tricky mechanisms to make it work properly (see the code)
3. It comes back to bite me every once in a while, bugs are filed about 
this.


The unfortunate thing is that if you want to have non-templated unit 
tests, you have to put them outside the struct itself. This sucks for 
documented unit tests, and for tests being close to the thing being 
tested. I'd love to have a way to specify that a unit test is really 
outside the struct, but still have it written inside. I'm not sure if it 
would be accepted though.


-Steve


Re: unittest blocks not being run inside of class and struct templates

2017-07-24 Thread NoBigDeal256 via Digitalmars-d-learn

On Tuesday, 25 July 2017 at 02:18:41 UTC, Adam D. Ruppe wrote:

On Tuesday, 25 July 2017 at 02:11:20 UTC, NoBigDeal256 wrote:
it passes when it should fail because the unittest block is 
never executed. Why is this?


Did you actually instantiate the class somewhere? A template 
has no concrete code unless created with an argument 
somewhere...


What if it's instantiated in another module? Right now I'm having 
issues where if I run 'dmd a.d b.d -unittest' and the class 
template in b.d is instantiated in a.d and it compiles and the 
tests inside my class template run as they should, but when using 
'dub test' the tests in my class template don't run at all as if 
it isn't instantiated in a.d even though it is. This is the 
original issue that I had that prompted me to create this thread.


Re: unittest blocks not being run inside of class and struct templates

2017-07-24 Thread NoBigDeal256 via Digitalmars-d-learn

On Tuesday, 25 July 2017 at 02:18:41 UTC, Adam D. Ruppe wrote:

On Tuesday, 25 July 2017 at 02:11:20 UTC, NoBigDeal256 wrote:
it passes when it should fail because the unittest block is 
never executed. Why is this?


Did you actually instantiate the class somewhere? A template 
has no concrete code unless created with an argument 
somewhere...


Well shit that was the issue. My mistake, I should have thought 
of that, but it makes total sense now.


What is the standard way of testing class templates in the 
context of a library where some of the classes may never actually 
be used by the library itself? I know I could just make a private 
module-level field declaration that just instantiates a template 
but that seems like an ugly way of handling it. Any suggestions 
on how you would handle this?


Re: unittest blocks not being run inside of class and struct templates

2017-07-24 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 25 July 2017 at 02:11:20 UTC, NoBigDeal256 wrote:
it passes when it should fail because the unittest block is 
never executed. Why is this?


Did you actually instantiate the class somewhere? A template has 
no concrete code unless created with an argument somewhere...