Jump to page: 1 2
Thread overview
Lookahead in unittest
May 10, 2017
Raiderium
May 10, 2017
Stefan Koch
May 11, 2017
Jacob Carlborg
May 10, 2017
Adam D. Ruppe
May 10, 2017
Raiderium
May 12, 2017
pineapple
May 12, 2017
H. S. Teoh
May 15, 2017
H. S. Teoh
May 13, 2017
Jonathan M Davis
May 10, 2017
Heyo,

On 2.074.0, the following test fails with "Error: undefined identifier 'B' "

unittest
{
	class A { B b; }
	class B { }
}

I can't figure out if this is intended behaviour. It's making a template-heavy module difficult to test. Would appreciate any help.

First post here, be gentle :)
May 10, 2017
On Wednesday, 10 May 2017 at 16:09:06 UTC, Raiderium wrote:
> Heyo,
>
> On 2.074.0, the following test fails with "Error: undefined identifier 'B' "
>
> unittest
> {
> 	class A { B b; }
> 	class B { }
> }
>
> I can't figure out if this is intended behaviour. It's making a template-heavy module difficult to test. Would appreciate any help.
>
> First post here, be gentle :)

It looks like this unitest-test block are treated like a function.

What is the surrounding code ?

If this is at module level then it is a bug.
May 10, 2017
On Wednesday, 10 May 2017 at 16:09:06 UTC, Raiderium wrote:
> I can't figure out if this is intended behaviour.

It is. A unittest is a function, and in functions, all declarations must be defined before used (just like local variables).

Sometimes, you can wrap it in a struct:

unittest {
  struct Decls {
    // put your decls here
  }

  with(Decls()) {
   // call funcs here
  }
}
May 10, 2017
On Wednesday, 10 May 2017 at 16:32:11 UTC, Adam D. Ruppe wrote:
> On Wednesday, 10 May 2017 at 16:09:06 UTC, Raiderium wrote:
>> I can't figure out if this is intended behaviour.
>
> It is. A unittest is a function, and in functions, all declarations must be defined before used (just like local variables).
>
> Sometimes, you can wrap it in a struct:
>
> unittest {
>   struct Decls {
>     // put your decls here
>   }
>
>   with(Decls()) {
>    // call funcs here
>   }
> }

Ah. I wasn't aware class declarations within functions (including unittest) were sensitive to their order, so that's something I've learned today. :)

I tried the with(Decls()) syntax and it worked perfectly, thanks Adam. I'd been haphazardly nesting unittest{} blocks within the struct, and it felt less than sanitary.

For full disclosure, the test I'm writing needs to create a reference cycle (as in, class B holding a reference to A), and it works properly if the classes are declared at module/class/struct level, but then either the class names pollute the module (which is just eww) or they're nested within a class/struct, which leads me to the current situation.

Consider my problem solved :) Thanks again Stefan and Adam for the replies.
May 11, 2017
On 2017-05-10 18:17, Stefan Koch wrote:

> It looks like this unitest-test block are treated like a function.

unittest blocks are lowered to functions.

-- 
/Jacob Carlborg
May 12, 2017
On 5/10/17 12:53 PM, Raiderium wrote:
> On Wednesday, 10 May 2017 at 16:32:11 UTC, Adam D. Ruppe wrote:
>> On Wednesday, 10 May 2017 at 16:09:06 UTC, Raiderium wrote:
>>> I can't figure out if this is intended behaviour.
>>
>> It is. A unittest is a function, and in functions, all declarations
>> must be defined before used (just like local variables).
>>
>> Sometimes, you can wrap it in a struct:
>>
>> unittest {
>>   struct Decls {
>>     // put your decls here
>>   }
>>
>>   with(Decls()) {
>>    // call funcs here
>>   }
>> }
>
> Ah. I wasn't aware class declarations within functions (including
> unittest) were sensitive to their order, so that's something I've
> learned today. :)
>
> I tried the with(Decls()) syntax and it worked perfectly, thanks Adam.
> I'd been haphazardly nesting unittest{} blocks within the struct, and it
> felt less than sanitary.
>
> For full disclosure, the test I'm writing needs to create a reference
> cycle (as in, class B holding a reference to A), and it works properly
> if the classes are declared at module/class/struct level, but then
> either the class names pollute the module (which is just eww) or they're
> nested within a class/struct, which leads me to the current situation.
>
> Consider my problem solved :) Thanks again Stefan and Adam for the replies.

Note, you can achieve what you want with version(unittest):

version(unittest)
{
   class A { B b; }
   class B { }
}

unittest
{
   // use A and B here
}

-Steve
May 12, 2017
On Friday, 12 May 2017 at 21:23:23 UTC, Steven Schveighoffer wrote:
> Note, you can achieve what you want with version(unittest):

Please prefer `private version(unittest){...}` if the module might be imported by someone else's code, as to not pollute it with unneeded symbols

May 12, 2017
On Fri, May 12, 2017 at 05:23:23PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: [...]
> Note, you can achieve what you want with version(unittest):
> 
> version(unittest)
> {
>    class A { B b; }
>    class B { }
> }
> 
> unittest
> {
>    // use A and B here
> }
[...]

This advice, unfortunately, needs to be tempered with caution about namespace pollution and accidental dependency of things outside unittests on things inside a version(unittest) block.  There's also the issue of library code introducing extraneous import dependencies that are really only necessary for unittesting, but get pulled in anyway because user code happens to compile with -unittest.


T

-- 
"Real programmers can write assembly code in any language. :-)" -- Larry Wall
May 13, 2017
On Friday, May 12, 2017 14:46:30 H. S. Teoh via Digitalmars-d-learn wrote:
> On Fri, May 12, 2017 at 05:23:23PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote: [...]
>
> > Note, you can achieve what you want with version(unittest):
> >
> > version(unittest)
> > {
> >
> >    class A { B b; }
> >    class B { }
> >
> > }
> >
> > unittest
> > {
> >
> >    // use A and B here
> >
> > }
>
> [...]
>
> This advice, unfortunately, needs to be tempered with caution about namespace pollution and accidental dependency of things outside unittests on things inside a version(unittest) block.  There's also the issue of library code introducing extraneous import dependencies that are really only necessary for unittesting, but get pulled in anyway because user code happens to compile with -unittest.

Yeah, that can get annoying, though I think that the only real problem in general is imports. If you use version(unittest) on imports, then you run the risk of having imports that are required for normal operation being only available when you compile with -unittest and not catching it. But unless you have a problem using version(unittest) types or functions in your actual code (which would be kind of weird), then I wouldn't expect it to be a problem.

However, in many cases, it makes sense to just move the declarations into the unittest blocks (especally if they're only used in one unittest block), and then you avoid the whole problem (though in this case, you'd want to mark the classes as static if you put them in the unittest block).

- Jonathan M Davis

May 13, 2017
On 5/12/17 5:46 PM, H. S. Teoh via Digitalmars-d-learn wrote:
> On Fri, May 12, 2017 at 05:23:23PM -0400, Steven Schveighoffer via Digitalmars-d-learn wrote:
> [...]
>> Note, you can achieve what you want with version(unittest):
>>
>> version(unittest)
>> {
>>    class A { B b; }
>>    class B { }
>> }
>>
>> unittest
>> {
>>    // use A and B here
>> }
> [...]
>
> This advice, unfortunately, needs to be tempered with caution about
> namespace pollution and accidental dependency of things outside
> unittests on things inside a version(unittest) block.  There's also the
> issue of library code introducing extraneous import dependencies that
> are really only necessary for unittesting, but get pulled in anyway
> because user code happens to compile with -unittest.

This actually already happens. Any imports count, even inside unittests.

But yes, this does mean that symbols in the version(unittest) are in the module namespace.

You could create a struct or class namespace to avoid the pollution, as long as you use really horrible names that wouldn't possibly conflict.

-Steve
« First   ‹ Prev
1 2