Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TAP support #326

Merged
merged 1 commit into from
Dec 22, 2015
Merged

TAP support #326

merged 1 commit into from
Dec 22, 2015

Conversation

vadimdemedes
Copy link
Contributor

This PR fixes #27.

It adds --tap flag to a CLI to generate TAP-compatible output, which can then be used with any 3rd-party reporters.

$ ava --tap example.js | tap-nyan

screen shot 2015-12-12 at 2 51 24 pm

Here are the things to be resolved before this PR can be merged:

  • Test tracked assertions in test/assert.js
  • Decide on assertion output
  • Test TAP output (and probably separate into own module)
  • Include unhandled rejections and exceptions into TAP output
  • Support fail-fast mode via Bail out!
  • Add information on enabling TAP output to Readme

Let's discuss!


module.exports = Assert;

var x = Assert.prototype;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to remove this.

@sindresorhus
Copy link
Member

Looks very promising! :) 🍰

Decide on assertion output

What specifically needs to be decided on?

api.skip[el] = skipFn;
api[el] = function () {
try {
var fn = assert[el].apply(assert, arguments);
var fn = self.assert[el].apply(self.assert, arguments);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to make assert a class? Can't we just track assertions here? Demanding the assert class track assertions is going to make it harder to support custom assertions down the road.

Is the issue simply that it is hard to know which argument is the message here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to make assert a class? Can't we just track assertions here?

I'm open to suggestions!

Demanding the assert class track assertions is going to make it harder to support custom assertions down the road.

It will, see my comment below.

Is the issue simply that it is hard to know which argument is the message here?

The issue lies in AVA's feature - concurrency. As you know, tests run concurrently, so we have to track which assertions happened during that particular test. That's why Assert class is needed, because that way we can safely get a list of test's assertions.

@vadimdemedes
Copy link
Contributor Author

Decide on assertion output
What specifically needs to be decided on?

Sorry for not making that clear. We need to decide what title do we display for assertions:

test something
  ✅ 'yes' === 'no'
  or
  ✅ t.is()
  or
  ✅ t.is('yes', 'no')

So, test have titles and assertion have titles too, so we need to decide on the latter.

@sindresorhus
Copy link
Member

We need to decide what title do we display for assertions

'yes' === 'no' and the power-assert output when t.ok()/t.notOk(). We should also show the assert message when provided.

@jamestalmage
Copy link
Contributor

@vdemedes - I know I linked it before somewhere, but here are the docs you need for the empower-core.

FYI: @twada keeps stuff he still considers "beta" under his GitHub account and only moves stuff to the power-assert-js GitHub group when he is committing to a stable, long-term API. That is why you had trouble finding those docs.

As for powerAssertContext, there is a good example of it's contents here. @twada may be able to provide a better link. You will likely need powerAssertContext.source.content.

Finally, we are going to need to come up with a solution for assertions like this:

t.same(foo, {
  blah: 'blah',
  bar: 'foo',
  zippo: [1, 2, 3]
});

That is probably a more than we want to log, even when compacted to a single line. We can probably do some pretty clever collapsing of the code eventually (i.e. t.same(foo, {blah: ...})). We could even change color to light gray for the parts we collapse.

For the first pass, maybe we don't use the powerAssertContext (or maybe only if source.content.length is less than some arbitrary number).

@twada
Copy link
Contributor

twada commented Dec 14, 2015

For multiline assertions, power-assert normalizes the assertion lines to single line to render diagrams on reporting.
So powerAssertContext.source.content is always in a form of single line, no matter how much lines original assertion has.

For example, In @jamestalmage's case, powerAssertContext.source.content is
t.same(foo, { blah: \'blah\', bar: \'foo\', zippo: [1, 2, 3] })'

@jamestalmage
Copy link
Contributor

powerAssertContext.source.content is always in a form of single line

Yes, my point was that even that will end up verbose given a large enough object declaration. I'm sure our eventual solution will share code with SuccinctReporter.

@@ -20,13 +21,14 @@ function Test(title, fn) {
title = null;
}

assert.is(typeof fn, 'function', 'you must provide a callback');
assert.equal(typeof fn, 'function', 'you must provide a callback');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick, but equal => strictEqual

@vadimdemedes
Copy link
Contributor Author

@jamestalmage So I tried to use latest changes to assertions and turned out it's not actually usable for tracking assertions. I inserted console.log(event) at the beginning of onAssertionEvent and it shows no useful information (in case there was no error):

{ originalMessage: undefined,
  enhanced: true,
  args: [ true, undefined ],
  assertionThrew: false,
  returnValue: undefined }

event.powerAssertContext is undefined.

The assertion is a simple t.true(true). Am I missing something?

@jamestalmage
Copy link
Contributor

I looked into this a bit.
Turns out, powerAssertContext only attaches when the code is sufficiently complex to warrant it:

These will not attach a powerAssertContext:

t.ok(true);
t.is('a', 'a');

These will:

var a = 'a';
t.ok(a);
t.is(a, 'a');
t.is({a: 'a'}.a, 'a');

It should still be possible to build something close to the original source using args.

@vadimdemedes
Copy link
Contributor Author

It should still be possible to build something close to the original source using args.

I don't think this will have good consequences, we need a stable solution. Otherwise we'll end up with a babel-like stream of issues.

@sindresorhus
Copy link
Member

Can we defer the assert title complications for later and focus on just getting some TAP output in this PR? We can just go for naive assert titles for now.

@jprichardson
Copy link

Can we defer the assert title complications for later and focus on just getting some TAP output in this PR? We can just go for naive assert titles for now.

👍 It's (no tap) the only thing that's preventing me from deep diving into Ava :)

@jamestalmage
Copy link
Contributor

defer the assert title complications for later

I agree. I think it will take us a while to figure that out correctly, and I don't want to hold up TAP support. Unfortunately, onAssert currently doesn't even tell you which method was called. @vdemedes - see #340 for a workaround on that (the identity function hack, not the whole PR).

@vadimdemedes
Copy link
Contributor Author

Ok, let's postpone it for now, I'll come up with something simpler. I'm off tomorrow, so I'll post updates the day after.

@jamestalmage will take a look, thanks.

@sindresorhus
Copy link
Member

Alright. I've opened an issue for it so we don't forget. #341

@vadimdemedes vadimdemedes force-pushed the tap-support branch 2 times, most recently from 74673c1 to 736a044 Compare December 21, 2015 13:23
@vadimdemedes
Copy link
Contributor Author

PR updated with additions to Readme. Now it can be merged and we'll handle assertion output later.


AVA can generate TAP output via `--tap` option for use with any 3rd-party reporters.

```bash
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use bash as it's not valid shell script with the $.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was using it, because sometimes it highlights executable name and symbols like |. Will remove it, no probs ;)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but the highlighting is very random.

output.push(' ...');

console.log(output.join('\n'));
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something like this would look nicer:

console.log([
    '# ' + err.message,
    format('not ok %d - %s', ++i, err.message),
    '  ---',
    '    name: ' + err.name,
    '    at: ' + getSourceFromStack(err.stack, 1),
    '  ...'
].join('\n'));

@sindresorhus
Copy link
Member

Can you add some tests?

@sindresorhus
Copy link
Member

And add tap as a keyword to package.json.

@sindresorhus sindresorhus changed the title [WIP] TAP support TAP support Dec 21, 2015
AVA can generate TAP output via `--tap` option for use with any 3rd-party reporters.

```bash
$ ava --tap | tap-spec
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be more fun to illustrate with the nyan reporter, right? You also need to show installing the reporter. Otherwise we'll end up with support issues on how it doesn't work...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include a screenshot or that'd be too much?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, drop the install instruction. We can't know if they want to use it locally or globally. It has to be globally installed if used like the above, or locally if used in a npm run script.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include a screenshot or that'd be too much?

Sure! Here you go. Make sure to use <img> and half its width so it becomes retina.

screen shot 2015-12-21 at 15 58 00

@vadimdemedes
Copy link
Contributor Author

@sindresorhus

Can you add some tests?

I will!

@vadimdemedes
Copy link
Contributor Author

I'm thinking if we should return generated output from lib/tap.js, instead of console.log()ing it from there. Would also be easier to test TAP output.

@sindresorhus
Copy link
Member

👍

@vadimdemedes vadimdemedes force-pushed the tap-support branch 3 times, most recently from 7639370 to cccb2cd Compare December 21, 2015 22:00
@vadimdemedes
Copy link
Contributor Author

PR updated according to all suggestions:

  • Improve readme and add a screenshot
  • Return TAP output, instead of console.log()ing it directly from lib/tap.js
  • Add tests for TAP
  • Add "tap" keyword to package.json
  • Clean up lib/tap.js

@@ -36,7 +37,8 @@ var cli = meow([
' --init Add AVA to your project',
' --fail-fast Stop after first test failure',
' --serial Run tests serially',
' --require Module to preload (Can be repeated)',
' --require Module to preload (Can be repeated)',,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double comma

@sindresorhus
Copy link
Member

LGTM

@sindresorhus
Copy link
Member

Support fail-fast mode via Bail out!

⬆️ Can you open an issue for this?

@sindresorhus
Copy link
Member

(and probably separate into own module)

I'm surprised there's no compliance suite any TAP producer could use. Would be so useful (hint hint). Something like https://github.com/promises-aplus/promises-tests

@jamestalmage
Copy link
Contributor

LGTM

I have run it against a number of projects, and the output looks great when everything passes. Something feels off when there are errors though:

classic reporter:

screenshot 2015-12-21 18 13 31

tail end of spec reporter:

screenshot 2015-12-21 18 18 01

Neither tells you which test the failure came from (these are not uncaught exceptions, but assertion errors).

@jamestalmage
Copy link
Contributor

:shipit: 👍 LGTM

We can improve the messages incrementally.

@vadimdemedes
Copy link
Contributor Author

@sindresorhus

Support fail-fast mode via Bail out!
⬆️ Can you open an issue for this?

I figured there's no need for this one, as we end the tests "safely". And not all reporters handle this stuff.

@jamestalmage Try to use tap-* reporters, not reporters for mocha, as it had some out-dated TAP output.

@vadimdemedes
Copy link
Contributor Author

I'm surprised there's no compliance suite any TAP producer could use. Would be so useful (hint hint).

@sindresorhus good idea!

@vadimdemedes
Copy link
Contributor Author

@sindresorhus @jamestalmage guys, need you to LGTM one more time. It does not want to merge it otherwise.

vadimdemedes pushed a commit that referenced this pull request Dec 22, 2015
@vadimdemedes vadimdemedes merged commit d4d8310 into master Dec 22, 2015
@vadimdemedes vadimdemedes deleted the tap-support branch December 22, 2015 07:27
@vadimdemedes
Copy link
Contributor Author

@sindresorhus @jamestalmage Never mind, merged!

@vadimdemedes
Copy link
Contributor Author

@sindresorhus
Copy link
Member

tap-dancing

So much tap! 💃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TAP support
5 participants