-
Notifications
You must be signed in to change notification settings - Fork 18
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
RFC: Spinal Tap (alternative proposal) #133
Comments
How does jest fit into this? Either way, i think that supporting TAP as the primary output format has always been the only viable choice, so i think this sounds like a good direction. |
ship it |
A thing I don't understand is the bit about an end-user workaround for "console.log-style" debugging (that'd otherwise malign TAP output) is just to use |
That's what i always do anyways, since stdout output is often being piped to other tools to consume. |
In light of the shift in direction per #133, I'm reverting (most of) cce0e4d so as to allow the next release to more similar to the previous, and to make upgrading easy, allowing most reporters to keep working with very minimal changes (if any). Instead, I'll focus on migrating consumers of js-reporters to use TAP tools directly where available, and to otherwise reduce use of js-reporters to purely the adapting and piping to TapReporter. * Revert `RunStart.testCounts` > `RunStart.counts` (idem RunEnd). * Revert `TestStart.suitName` > `TestStart.parentName` (idem TestEnd). * Revert Test allowing Test as child, restore Suite. This un-fixes #126, which will be declined. Frameworks adapted to TAP by js-reporters will not supported nested tests. Frameworks directly providing TAP 13 can one of several strategies to express relationships in a backwards-compatible manner, e.g. like we do in js-reporters by flattening with '>' symbol, or through indentation or through other manners proposed in TestAnything/testanything.github.io#36. Refer to #133 for questions about how to support TAP.
The js-reporters project is slowly coming to an and per qunitjs/js-reporters#133. I expect going forward it will continue to be maintained for some time to provide TAP streams from older versions of testing frameworks. However, all major testing frameworks now have built-in or mature plugins for TAP output. As such, I'd prefer to maintain TapReporter directly in the QUnit repository. Co-authored-by: Florentin Simion <[email protected]> Co-authored-by: Franziska Carstens <[email protected]> Co-authored-by: Martin Olsson <[email protected]> Co-authored-by: Robert Jackson <[email protected]> Co-authored-by: Timo Tijhof <[email protected]> Co-authored-by: Trent Willis <[email protected]> Co-authored-by: Zachary Mulgrew <[email protected]> Co-authored-by: jeberger <[email protected]>
This change makes the reporters, from the js-reporters package, generally available through the primary distribution, instead of being limited to the QUnit CLI. The built-in reporters are exposed via `QUnit.reporters`. This is a major step toward truly supporting the TAP ecosystem, and popular runners such as Airtap for browser testing, and the node-tap CLI (why not). There is still more work to be done, though, such as making the library more friendly to require'ing, and further decoupling of our HTML Runner/Reporter. As such, this remains experimental as of yet. It can be tried out by calling `QUnit.reporters.tap.init(QUnit)` between importing QUnit and importing your tests, e.g. from an inline script or setup script. This overall direction is outlined in qunitjs/js-reporters#133, and as such apart from bridging older versions, the js-reporters package will not be as actively developed going forward. I'm copying the reporters we developed there into QUnit repository for further developement here, without the indirection of that package. Co-authored-by: Florentin Simion <[email protected]> Co-authored-by: Franziska Carstens <[email protected]> Co-authored-by: Martin Olsson <[email protected]> Co-authored-by: Robert Jackson <[email protected]> Co-authored-by: Timo Tijhof <[email protected]> Co-authored-by: Trent Willis <[email protected]> Co-authored-by: Zachary Mulgrew <[email protected]> Co-authored-by: jeberger <[email protected]>
This change makes the reporters, from the js-reporters package, generally available through the primary distribution, instead of being limited to the QUnit CLI. The built-in reporters are exposed via `QUnit.reporters`. This is a major step toward truly supporting the TAP ecosystem, and popular runners such as Airtap for browser testing, and the node-tap CLI (why not). There is still more work to be done, though, such as making the library more friendly to require'ing, and further decoupling of our HTML Runner/Reporter. As such, this remains experimental as of yet. It can be tried out by calling `QUnit.reporters.tap.init(QUnit)` between importing QUnit and importing your tests, e.g. from an inline script or setup script. This overall direction is outlined in qunitjs/js-reporters#133, and as such apart from bridging older versions, the js-reporters package will not be as actively developed going forward. I'm copying the reporters we developed there into QUnit repository for further developement here, without the indirection of that package. Co-authored-by: Florentin Simion <[email protected]> Co-authored-by: Franziska Carstens <[email protected]> Co-authored-by: Martin Olsson <[email protected]> Co-authored-by: Robert Jackson <[email protected]> Co-authored-by: Timo Tijhof <[email protected]> Co-authored-by: Trent Willis <[email protected]> Co-authored-by: Zachary Mulgrew <[email protected]> Co-authored-by: jeberger <[email protected]>
This change makes the reporters, from the js-reporters package, generally available through the primary distribution, instead of being limited to the QUnit CLI. The built-in reporters are exposed via `QUnit.reporters`. This is a major step toward truly supporting the TAP ecosystem, and popular runners such as Airtap for browser testing, and the node-tap CLI (why not). There is still more work to be done, though, such as making the library more friendly to require'ing, and further decoupling of our HTML Runner/Reporter. As such, this remains experimental as of yet. It can be tried out by calling `QUnit.reporters.tap.init(QUnit)` between importing QUnit and importing your tests, e.g. from an inline script or setup script. This overall direction is outlined in qunitjs/js-reporters#133, and as such apart from bridging older versions, the js-reporters package will not be as actively developed going forward. I'm copying the reporters we developed there into QUnit repository for further developement here, without the indirection of that package. Co-authored-by: Florentin Simion <[email protected]> Co-authored-by: Franziska Carstens <[email protected]> Co-authored-by: Martin Olsson <[email protected]> Co-authored-by: Robert Jackson <[email protected]> Co-authored-by: Timo Tijhof <[email protected]> Co-authored-by: Trent Willis <[email protected]> Co-authored-by: Zachary Mulgrew <[email protected]> Co-authored-by: jeberger <[email protected]>
== Integrate js-reporters spec == Keep the link to the js-reporters project for now, but no longer rely on it for discovery. The spec was written for implementors, which makes it a suboptimal reading experience for end-users. It also suffered from numerous nullable properties that in practice with QUnit are either never null or always null. In our docs, I've left these off or explicitly described them in their reliable non-null form to avoid any doubt or confusion over how or why they behave a certain way. Note that as of js-reporters 2.0, much of the spec has been removed which QUnit currently still implements for compatibility (such as upfront recursively declared child suites). These have not been documented and will be removed in QUnit 3.0. Ref https://github.com/js-reporters/js-reporters/releases/tag/v2.0.0. The integration of the spec, rather than improving or creating a page in the js-reporters repo for end-users, is motivated by qunitjs/js-reporters#133, in which I conclude that for now it is a better use of our effort for any re-usable cross-framework reporters to consume TAP rather than tight runtime coupling. This also has the benefit of not pushing down the "serialize actual value" and "format a diff" problems down to end-consumers, which in practice are often done poorly or not at all. == Document unofficial `done` details == For `done()`, the `details.modules` property was added by commit 168b048 in QUnit 1.16 (2014) for internal use by HTML Reporter. It was never documented, however. It originally came with a `test` property as well, but that hasn't been in use since commit 43a3d87 in QUnit 2.7 (2018). Keep this for now since it's not adding delay or complexity, but I've left a note to remove this in QUnit 3.0. Document the rest as now-officially supported, with retroactive changelog. Also document the oft-overlooked caveat with the legacy assertion counts exposed from `QUnit.done()`. I believe the community has large moved away from using the data provided by this callback. For example, gruntjs/grunt-contrib-qunit#137. Recommend `on('runEnd')` instead.
== Integrate js-reporters spec == Keep the link to the js-reporters project for now, but no longer rely on it for discovery. The spec was written for implementors, which makes it a suboptimal reading experience for end-users. It also suffered from numerous nullable properties that in practice with QUnit are either never null or always null. In our docs, I've left these off or explicitly described them in their reliable non-null form to avoid any doubt or confusion over how or why they behave a certain way. Note that as of js-reporters 2.0, much of the spec has been removed which QUnit currently still implements for compatibility (such as upfront recursively declared child suites). These have not been documented and will be removed in QUnit 3.0. Ref https://github.com/js-reporters/js-reporters/releases/tag/v2.0.0. The integration of the spec, rather than improving or creating a page in the js-reporters repo for end-users, is motivated by qunitjs/js-reporters#133, in which I conclude that for now it is a better use of our effort for any re-usable cross-framework reporters to consume TAP rather than tight runtime coupling. This also has the benefit of not pushing down the "serialize actual value" and "format a diff" problems down to end-consumers, which in practice are often done poorly or not at all. == Document unofficial `done` details == For `done()`, the `details.modules` property was added by commit 168b048 in QUnit 1.16 (2014) for internal use by HTML Reporter. It was never documented, however. It originally came with a `test` property as well, but that hasn't been in use since commit 43a3d87 in QUnit 2.7 (2018). Keep this for now since it's not adding delay or complexity, but I've left a note to remove this in QUnit 3.0. Document the rest as now-officially supported, with retroactive changelog. Also document the oft-overlooked caveat with the legacy assertion counts exposed from `QUnit.done()`. I believe the community has large moved away from using the data provided by this callback. For example, gruntjs/grunt-contrib-qunit#137. Recommend `on('runEnd')` instead.
Hi everyone,
Don't worry if you haven't kept up with recent developments here or don't remember how js-reporters works. I'm proposing a new direction, and everything you need to know is right here. What follows is a progress update on how everyone is doing, and what we can do next.
What is this?
It's a proposal for adopting TAP, a text format for reporting progress and results of software tests. Unlike the current iteration of js-reporters, TAP is a mature and already widely-adopted protocol.
Remind me, why?
For test runners and browser orchestrators :
For test frameworks:
Are we there yet?
Update on test frameworks (/cc @js-reporters/intern, @js-reporters/jasmine, @js-reporters/mocha, @js-reporters/qunit, @js-reporters/tape, @js-reporters/vows).
By now, all the frameworks I checked provide TAP streams, or have seemingly good plugins for it. So, on the framework side, we're mostly there already.
--reporter
for other reporters that accept an EventEmitter with QUnit-specific and CRI (working draft) events. The same reporter API is available in the browser, although its TAP reporter is currently missing in the browser build, so perhaps it could provide it there as well going forward.--reporter
for other reporters that accept an EventEmitter with Mocha-specific events. In the browser, the TAP reporter is available as well, printed toconsole.log
.--reporter
for reporters that accepts its EventEmitter. In the browser,jasmine.addReporter()
provides that same API. A plug-in is available for TAP output, supported and tested both in Node.js and the browser, printed toconsole.log
.console.log
. It offers thecreateStream()
method for custom reporters, both from a web page and from Node process. Its ecosystem generally embraces the Linux philosophy of pipes where each reporter is its own process, with its own TAP parser, reading from stdin. These reporters are already highly portable, and e.g. usable atop output from QUnit and Mocha.process.stdout
. I found some discussion and past change logs indicating that it worked via browserify, but I'm unsure of its current status.And update on test runners and orchestrators (/cc @js-reporters/integration, @js-reporters/node-tap, @js-reporters/intern):
require()
's a framework and outputs TAP, this CLI offers parallel testing, code coverage, filtering, etc. It aggregates TAP streams and supports--reporter
.What about the old CRI draft?
See: Common Reporter Interface (Working Draft).
Having worked now on almost all layers of the stack (unit and integration framework, orchestrators, browser launchers, CLI runners, cloud services, reporting plugins, etc), I think our previous programmatic and EventEmitter-based standardisation is problematic in a number of ways:
Hard to inject in browsers. I think there's great value in having isomorphic JavaScript libraries actually test their code on both Node.js and in multiple real browsers. This is now easier than ever with Firefox and Chromium having built-in headless modes and DevTools/RemoteDebug protocols [1], [2], and beyond that through WebDriver (for BrowserStack and SauceLabs). However, sharing your test suite between Node, an automated browser, and manual debugging can be though when orchestrators need to inject their client into the web page. There are generally one of three approaches I see:
</body>
and assume tests will not start before window.onload).Limited to JavaScript. JavaScript is big, but TAP is no doubt bigger in scope. I don't particularly foresee mass adoption of by JS developers to pipe results into reporters written using other runtimes, but then again we do have esbuild and rslint seeing great attention. While JS developers may be less likely to want to "figure out" installing the right version of Python or PHP and interact with dependencies in those ecosystems etc., there is a lot of room for Go and Rust binaries and APT/Homebrew package managers distributing tools that "just work". Once you open this door, there is also room for passive adoption in other environments, such as a native IDE on your platform that can run tests for you in an integrated shell, and aggregate or do other useful things with TAP output if it detects it.
Extended metadata. There are three capabilities that appear to be widely used in testing frameworks, and were part of the CRI working draft, that are currently not natively recognised in TAP 13.
# START <NR. test name>
comment could certainly work. This is mainly used today in real-time HTML and IDE consumers to show which test(s) are currently executing, which can help improve the debugging experience as well as to get a feel of where much time is spent or where an otherwise complex failure may have occurred.FAQ
Isn't console.log fragile?
I've long held that TAP was insufficient for our needs, that we need a standardised way for reporters and orchestrators to discover and access the event stream in-process (especially in browsers). It felt wrong to claim
console.log
completely for ourselves, or to have to monkey-patch it when you need to consume it client-side in a browser. Over the past year, I've realised (finally) that I think this lets perfect be the enemy of good. "Just" consuming the console output from a browser massively simplifies the problem we are trying to solve, and at least I'm convinced it's worth the small sacrifice.Conceptually, I think it's fair that an application does not send data to the console when it is under test and not asked or instructed to respond to someone in stdout or console. The one use case I've come across where source code does regularly use the console is for deprecation warnings and other error messages. These may or may not be useful or intentionally enabled in CI, but I think it's not our place to disrupt or disallow that. But, we also don't need to, since those go to a different channel than
console.log
. If a legacy code base finds unwanted messages are sent to the main log, I suppose they could as a quick initial mitigation resort to something likeconsole.log = function (){}
in their test bootstrap (after importing the test framework and/or TAP reporter), or evenconsole.log = console.info
to preserve but it in a different channel.This means WebDriver and DevTools/RemoteDebug-based runners don't have to inject anything, and can simply use native and pre-existing means to consume the browser's console log.
Prior art: Testling by @substack (ref tape-testing/testling#93), karma-tap by @bySabi, tap-console-parser by @Jam3, and more.
Next steps
Are we missing anything? Do you think this is feasible? Let us know!
If you use projects that don't native support TAP (like Karma, WebDriver, Grunt to launch Headless Firefox or Chromium via Puppeteer, etc.), consider giving it a try to use TAP to format the intermediary communication and let us know how this works out for you. Or if you do this already, how has the experience been? Have you run into issues or would like additional support from upstreams?
The text was updated successfully, but these errors were encountered: