haxetink / tink_unittest

Tinkerbell Unit Testing
https://haxetink.github.io/tink_unittest
16 stars 4 forks source link

Remove @:excluded/not-@:included tests at compile time #17

Open kevinresol opened 5 years ago

kevinresol commented 5 years ago

For @:exclude it should be easy. Just inject build macro and remove fields with such meta.

For @:include it might be tricky. We need to process all test classes too see if there are any @:include first, then exclude anything else.

Any ideas?

back2dos commented 5 years ago

For what purpose exactly?

kevinresol commented 5 years ago

Main advantage is that those excluded tests are no longer required to be type-able, only valid syntax is enough. It is useful when in the middle of refactoring, etc.

back2dos commented 5 years ago

For that we'd have to make the suite be processed by a build macro though.

Pruning non-included tests might work if you delay typing of the function bodies (e.g. via tink.macro.Exprs.bounce), hoping that all the build macros are triggered up front. What this means though is that you have to be very careful about what you're typing when. I think passing every expression to Context.typeof in TestBatch.make might trigger things in the right order.

kevinresol commented 5 years ago

First of all I need to understand bounce(), which I have been failed to do so.

back2dos commented 5 years ago

It "bounces" macro execution through the compiler. It takes a function that is meant to produce an expression "later". So it registers that function with an id, then it returns a macro call with that id is param. When the typer gets to that macro call, it executes it, the delayed call is looked up by id, executed and the resulting expression is returned.

Example:

myMacro(
  for (i in 0...100)
    @magic i;
);
//where
macro static function myMacro(e:Expr)
  return (function applyMagic(e:Expr) return switch e {
    case macro @magic $v: 
      trace(Context.typeof(v));
      v;
    default: e.map(applyMagic);
  })(e);

This will give you unknown identifier i, because while mapping the loop body, the containing loop is not typed yet. Instead, you can do this:

macro static function myMacro(e:Expr)
  return (function applyMagic(e:Expr) return switch e {
    case macro @magic $v: 
      (function () {
        trace(Context.typeof(v));
        return v;
      }).bounce();
    default: e.map(applyMagic);
  })(e);

It's kind of like return a call to another macro from a macro, except that instead of having to define the returned macro, you can just pass an anonymous function.

That said, given how typing works, there's a chance (limited as it may be) that actually you don't even need to delay expression typing, because the compiler tries to do that as late as possible anyway.