2018-02-28 10:30:39 +01:00
|
|
|
# doctest-ts: doctests for TypeScript
|
|
|
|
|
2018-02-28 10:54:06 +01:00
|
|
|
Say you have a file src/hasFoo.ts with a function like hasFoo:
|
2018-02-28 10:30:39 +01:00
|
|
|
|
|
|
|
```typescript
|
|
|
|
function hasFoo(s: string): boolean {
|
|
|
|
return null != s.match(/foo/i)
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
You can now make documentation and unit tests for this function in one go:
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
/** Does this string contain foo, ignoring case?
|
|
|
|
|
|
|
|
hasFoo('___foo__') // => true
|
|
|
|
hasFoo(' fOO ') // => true
|
|
|
|
hasFoo('Foo.') // => true
|
|
|
|
hasFoo('bar') // => false
|
|
|
|
hasFoo('fo') // => false
|
|
|
|
hasFoo('oo') // => false
|
|
|
|
|
|
|
|
*/
|
|
|
|
function hasFoo(s: string): boolean {
|
|
|
|
return null != s.match(/foo/i)
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2018-02-28 10:54:06 +01:00
|
|
|
Since the function is not exported we can only test this by either editing or copying the entire file and gluing on tests at the end.
|
|
|
|
This library goes for the second approach: making a copy of the file with the translated tests at the end. Run it like so:
|
2018-02-28 10:30:39 +01:00
|
|
|
|
|
|
|
```sh
|
|
|
|
$ doctest-ts src/hasFoo.ts
|
|
|
|
Writing src/hasFoo.doctest.ts
|
|
|
|
```
|
|
|
|
|
|
|
|
The contents of `src/hasFoo.doctest.ts` is the original file prepended to the doctests rewritten as unit tests.
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
/** Does this string contain foo, ignoring case?
|
|
|
|
|
|
|
|
hasFoo('___foo__') // => true
|
|
|
|
hasFoo(' fOO ') // => true
|
|
|
|
hasFoo('Foo.') // => true
|
|
|
|
hasFoo('bar') // => false
|
|
|
|
hasFoo('fo') // => false
|
|
|
|
hasFoo('oo') // => false
|
|
|
|
|
|
|
|
*/
|
|
|
|
function hasFoo(s: string): boolean {
|
|
|
|
return null != s.match(/foo/i)
|
|
|
|
}
|
|
|
|
|
|
|
|
import * as __test from "tape"
|
|
|
|
__test("hasFoo", t => {t.deepEqual(hasFoo("___foo__"), true, "true")
|
|
|
|
t.deepEqual(hasFoo(" fOO "), true, "true")
|
|
|
|
t.deepEqual(hasFoo("Foo."), true, "true")
|
|
|
|
t.deepEqual(hasFoo("bar"), false, "false")
|
|
|
|
t.deepEqual(hasFoo("fo"), false, "false")
|
|
|
|
t.deepEqual(hasFoo("oo"), false, "false")
|
|
|
|
;t.end()})
|
|
|
|
```
|
|
|
|
|
|
|
|
This can now be run with the tape runner or ts-node:
|
|
|
|
|
|
|
|
```
|
|
|
|
$ ts-node src/hasFoo.doctest.ts | tap-diff
|
|
|
|
hasFoo
|
|
|
|
✔ true
|
|
|
|
✔ true
|
|
|
|
✔ true
|
|
|
|
✔ false
|
|
|
|
✔ false
|
|
|
|
✔ false
|
|
|
|
Done in 0.37s.
|
|
|
|
|
|
|
|
passed: 6 failed: 0 of 6 tests (171ms)
|
|
|
|
|
|
|
|
All of 6 tests passed!
|
|
|
|
```
|
|
|
|
|
2018-03-05 17:15:31 +01:00
|
|
|
There are four different outputs available:
|
|
|
|
|
|
|
|
* tape
|
|
|
|
* AVA
|
|
|
|
* jest
|
|
|
|
* mocha (using chai)
|
|
|
|
|
|
|
|
Pull requests for other test runners are welcome.
|
2018-02-28 10:30:39 +01:00
|
|
|
|
|
|
|
## Watching file changes
|
|
|
|
|
|
|
|
We can tell `doctest-ts` to watch for file changes and report which files it has written.
|
|
|
|
It tries to be a good unix citizen and thus writes the files it has created on stdout (and some info on stderr).
|
|
|
|
This makes it possible to run test runners on each line on stdout like so:
|
|
|
|
|
|
|
|
```sh
|
|
|
|
ts-node src/main.ts --watch src/hasFo.ts |
|
|
|
|
while read file; do echo running tape on $file; ts-node $file | tap-diff; done
|
|
|
|
```
|
|
|
|
|
|
|
|
Let's say we remove the ignore case `i` flag from the regex in `hasFoo`. We get this output (automatically):
|
|
|
|
```
|
|
|
|
Writing src/hasFoo.doctest.ts
|
|
|
|
running tape on src/hasFoo.doctest.ts
|
|
|
|
|
|
|
|
hasFoo
|
|
|
|
✔ true
|
|
|
|
✖ true at Test.t (src/hasFoo.doctest.ts:18:3)
|
|
|
|
[-false-][+true+]
|
|
|
|
✖ true at Test.t (src/hasFoo.doctest.ts:19:3)
|
|
|
|
[-false-][+true+]
|
|
|
|
✔ false
|
|
|
|
✔ false
|
|
|
|
✔ false
|
|
|
|
|
|
|
|
passed: 4 failed: 2 of 6 tests (264ms)
|
|
|
|
|
|
|
|
2 of 6 tests failed.
|
|
|
|
```
|
|
|
|
|
|
|
|
# License
|
|
|
|
|
|
|
|
MIT
|