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

feat: deno test --docs support #7916

Closed
wants to merge 60 commits into from

Conversation

iykekings
Copy link

@iykekings iykekings commented Oct 10, 2020

Closed #6124 in favour of this.

This PR adds --docs to deno test sub-command for running tests on JSDoc @example blocks.

To use:

have code blocks in @example sections with three back-ticks as in markdown code blocks
deno test --docs runs all non-test files
Imports are done relative to root path, eg.
src/linkedlist.ts

export class Linkedlist<T>  {
// skipped lines
 /**
 * @param list - LinkedList<T>
 * @example <caption>Linkedlist.compareWith</caption>
 * import { LinkedList } from './src/linkedlist.ts';
 * const testArr = [1, 2, 3, 4, 5, 6, 78, 9, 0, 65];
 * const firstList = new LinkedList<number>();
 * const secondList = new LinkedList<number>();
 * for (let data of testArr) {
 *   firstList.insertNode(data);
 *   secondList.insertNode(data);
 * }
 * const result = firstList.compareWith(secondList);
 * assert.assertEquals(result, true);
 * @returns boolean
 */
  compareWith(list: LinkedList<T>): boolean {
    let current1 = this.head;
    let current2 = list.head;
    while (current1 && current2) {
      if (current1.data !== current2.data) return false;
      if (current1.next && !current2.next && !current1.next && current2.next) {
        return false;
      }
      current1 = current1.next;
      current2 = current2.next;
    }
    return true;
  }
}
  • All functions exported from https://deno.land/std/testing/asserts.ts can be used without importing them in an assert object. (assert.assert, assert.assertEquals, assert.assertNotEquals etc.)

  • await keyword can be used without wrapping in async function. NB: This is not due to TLA, but await will be detected in the example and the generated test is wrapped in an async function.

  • supports caption tag on @example block and used name of the test, by default test result is printed like this test src/linkedlist.ts - (line 160) ... ok (0ms), but with caption, like in the example above it will be test src/linkedlist.ts - Linkedlists.compareWith (line 160) ... ok (0ms)

  • Supports multiple @example blocks in one JSDoc comment

To ignore test:

  • wrap @example code block with back-ticks

  • Tag the three opening back-ticks with ignore, and it will be picked up but not tested, will be recorded by Deno test as ignored.

  • Tag the three opening back-ticks with text, and it will be seen as normal text

This is inspired by rustdoc --test

Example output
Screenshot 2020-10-09 at 14 05 41

Resolves #4716

iykekings and others added 30 commits May 27, 2020 13:09
* fix clippy errors

* break extract_jsdoc_examples to smaller fns

* fix error when ran without arguments
* test: extract_jsdoc_examples

* add more tests

* formatting
@bartlomieju bartlomieju changed the title Deno Doctest Support - continuation of #6124 feat: deno test --docs support Oct 11, 2020
@lucacasonato lucacasonato added this to the 1.5.0 milestone Oct 19, 2020
@bartlomieju bartlomieju self-requested a review October 19, 2020 12:57
@bartlomieju bartlomieju self-assigned this Oct 19, 2020
cli/doctest_runner.rs Outdated Show resolved Hide resolved
cli/doctest_runner.rs Outdated Show resolved Hide resolved
Comment on lines +252 to +259
pub fn is_supported_doctest(path: &Path) -> bool {
let valid_ext = ["ts", "tsx", "js", "jsx"];
path
.extension()
.and_then(OsStr::to_str)
.map(|ext| valid_ext.contains(&ext) && !is_supported(path))
.unwrap_or(false)
}
Copy link
Member

Choose a reason for hiding this comment

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

Not really sure what's going on here, @iykekings please explain

Copy link
Author

Choose a reason for hiding this comment

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

This is like opposite of is_supported for normal test files. It ensures doc tests are not run on test files and also that the file format is of normal expected type

Comment on lines +261 to +282
fn extract_test_tag(input: &str) -> Option<&str> {
TEST_TAG_PATTERN
.captures(input)
.and_then(|m| m.get(1).map(|c| c.as_str()))
}

fn extract_caption(input: &str) -> Option<&str> {
CAPTION_PATTERN
.captures(input)
.and_then(|m| m.get(1).map(|c| c.as_str()))
}

fn extract_imports(input: &str) -> Vec<&str> {
IMPORT_PATTERN
.captures_iter(input)
.filter_map(|caps| caps.get(0).map(|m| m.as_str()))
.collect()
}

fn has_await(input: &str) -> bool {
AWAIT_PATTERN.find(input).is_some()
}
Copy link
Member

Choose a reason for hiding this comment

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

Those utils seems a little brittle 😬 we should probably leverage SWC for this purpose, but I guess it's alright for first pass

Copy link
Author

Choose a reason for hiding this comment

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

Yeah I think so too, will have to parse each of the examples with swc

cli/main.rs Outdated Show resolved Hide resolved
@kitsonk kitsonk self-assigned this Oct 23, 2020
@bartlomieju
Copy link
Member

This PR requires more work before it can be landed; mainly it needs to use SWC for parsing instead of regexes.

I'm removing this PR from 1.5.0 milestone - instead it will be landed in 1.5.x. This feature is hidden behind --unstable flag so we can land it anytime.

@bartlomieju bartlomieju removed this from the 1.5.0 milestone Oct 25, 2020
@bartlomieju bartlomieju added this to the 1.6.0 milestone Nov 21, 2020
@wperron
Copy link
Contributor

wperron commented Nov 28, 2020

I'm just not sure about auto-importing asserts; it'd be nice to be able to simply copy paste the code block from the doc and run it as-is, as it stands one would need to add import * as assert from "https://deno.land/std/testing/asserts.ts" to the example block

@bartlomieju
Copy link
Member

I'm just not sure about auto-importing asserts; it'd be nice to be able to simply copy paste the code block from the doc and run it as-is, as it stands one would need to add import * as assert from "https://deno.land/std/testing/asserts.ts" to the example block

@wperron I've already requested to remove this feature, I think it's not included in the PR anymore?

@ry ry modified the milestones: 1.6.0, 1.7.0 Dec 11, 2020
@bartlomieju bartlomieju mentioned this pull request Dec 18, 2020
22 tasks
@lucacasonato lucacasonato removed this from the 1.7.0 milestone Jan 17, 2021
Base automatically changed from master to main February 19, 2021 14:58
@bartlomieju
Copy link
Member

Closing as stale because of numerous changes to test runner since this PR was open.

Thank you @iykekings this PR was a great base for @caspervonb, who's working on a new version with simpler API.

@bartlomieju bartlomieju closed this May 3, 2021
@iykekings
Copy link
Author

Thanks a lot @bartlomieju
@caspervonb 🔥👍

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.

deno test should run jsdoc example code
6 participants