leobalter / goiabada

experimental project providing a very simple (and incomplete) unit test tool written using ES6 features.
Other
25 stars 4 forks source link

async/await support #16

Open jaydson opened 9 years ago

jaydson commented 9 years ago

I'd love async/await support for async code. To test something today, as i can see, we need to do something like that:

goiabada.test( assert => {
    assert.ok( true, "it works!" );
    assert.end();
});

My proposal using async/await:

let assert = await goiabada.test("basics");
await assert.ok(true, "it works!");
await assert.equal( 1, "1", "equal assertion pass" );

I didn't look deeply at the Goibada code yet, but i don't think it will be so hard to implement something like my proposal.

Thoughts here? //cc @leobalter @UltCombo

leobalter commented 9 years ago

TBQH, I still need to read the documentation on async/await, but that leads me to some questions:

currently, test returns a promise, with the test results.

goiabada.test("basics").then( results => { ... } );

Maybe this should change to something more useful, maybe returning the assert object given at the test should be better:

goiabada.test("basics", t => {
  setTimeout( () => {
    t.ok(true);
    t.end();
  });
).then( t => {
  t.ok(true);
  t.end();
});

Where I believe the await method should fit is the test runner function. In other words, replacing the generator for a proper async function.

UltCombo commented 9 years ago

Perhaps goiabada.test could accept an async function as argument, then you can just await inside the callback. E.g.:

goiabada.test(async assert => {
  assert.ok(await someAsyncFunction(), "it works!");
});

Of course, the goiabada core would still need to undergo some changes to support the async logic to wait until the async assertions end and execute them in sequence (to avoid concurrent tests and log the results in the correct order).

@leobalter Async functions implicitly return promise objects, so it shouldn't be too hard to implement this asynchronous control flow.

jaydson commented 9 years ago

Here's a silly sample as how we can implement such a thing:

async function test() {
  return new Promise(function(resolve, reject) {
    resolve({
      ok : function(){
        console.log('OK');
      }
    })
  });
};

(async () => {
  let assert = await test("basics");
  await assert.ok();
}());
leobalter commented 9 years ago

Well, this is an open canvas, there's no release version yet, so I'm up to break it a little.

I'm not able to do this alone this week, I would love if you could send some more PR/suggestions

UltCombo commented 9 years ago

It would be nice to consider some real (yet simple) async test use cases. This way, it would be easier to discuss which syntax better fits real use cases, and the viability of implementing it.

jaydson commented 9 years ago

I tried to hack Goiabada last weekend, but i can't find a way to change the test method. Actually, i didn't understand yet how Goiabada queue works.

Here for example: https://github.com/leobalter/goiabada/blob/master/lib/goiabada.js#L54 @leobalter, can you please describe what is happening there? I mean, the test method returns an promise that returns assert. Where this promise is resolved?

leobalter commented 9 years ago

https://github.com/leobalter/goiabada/blob/master/lib/goiabada.js#L22

It returns the assert object for that test. I pushed a new commit to simplify the run method and clarify the same used object there.

jaydson commented 9 years ago

Now i got it. Simulation below:

async function test() {
  return new Promise( testResolve => {
     console.log('queue');
     setTimeout(function() {
       testResolve({ ok : 'wow'});
     }, 2000);
   }).then( assert => {
      console.log('assert');
   });
};

(async () => {
  let assert = await test();
  let result = await assert.ok;
  console.log(result); //wow
}());

I'll try again tonight.