Add --ignore as option

This commit is contained in:
Pieter Vander Vennet 2022-04-08 04:39:17 +02:00
parent c21c4e2b0b
commit 09dfb13a07
7 changed files with 77 additions and 16 deletions

17
package-lock.json generated
View file

@ -1,22 +1,23 @@
{ {
"name": "doctest-ts-improved", "name": "doctest-ts-improved",
"version": "0.6.0", "version": "0.8.5",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "doctest-ts-improved", "name": "doctest-ts-improved",
"version": "0.6.0", "version": "0.8.5",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@types/chai": "^4.3.0", "@types/chai": "^4.3.0",
"chai": "^4.3.6", "chai": "^4.3.6",
"global": "^4.3.2", "global": "^4.3.2",
"mocha": "^9.2.2", "mocha": "^9.2.2",
"process-yargs-parser": "^2.1.0",
"typescript": "^4.6.2" "typescript": "^4.6.2"
}, },
"bin": { "bin": {
"doctest-ts": "dist/src/main.js" "doctest-ts-improved": "dist/main.js"
}, },
"devDependencies": { "devDependencies": {
"@types/chokidar": "^1.7.5", "@types/chokidar": "^1.7.5",
@ -1372,6 +1373,11 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true "dev": true
}, },
"node_modules/process-yargs-parser": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz",
"integrity": "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q=="
},
"node_modules/randombytes": { "node_modules/randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@ -3014,6 +3020,11 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true "dev": true
}, },
"process-yargs-parser": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz",
"integrity": "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q=="
},
"randombytes": { "randombytes": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",

View file

@ -1,7 +1,7 @@
{ {
"$schema": "http://json.schemastore.org/package", "$schema": "http://json.schemastore.org/package",
"name": "doctest-ts-improved", "name": "doctest-ts-improved",
"version": "0.8.5", "version": "0.8.6",
"description": "doctest support for typescript with Mocha", "description": "doctest support for typescript with Mocha",
"main": "src/main.ts", "main": "src/main.ts",
"bin": { "bin": {
@ -9,9 +9,10 @@
}, },
"scripts": { "scripts": {
"build": "tsc && chmod 755 dist/main.js", "build": "tsc && chmod 755 dist/main.js",
"gen": "ts-node src/main.ts",
"test": "ts-node src/main.ts examples/ && ts-node src/main.ts src/ && mocha --require ts-node/register examples/*.ts src/*.ts", "test": "ts-node src/main.ts examples/ && ts-node src/main.ts src/ && mocha --require ts-node/register examples/*.ts src/*.ts",
"prettier": "rm -v -f {src,test}/*doctest.ts && prettier --list-different --write src/*ts* test/*ts*", "prettier": "rm -v -f {src,test}/*doctest.ts && prettier --list-different --write src/*ts* test/*ts*",
"publish": "npm run build && npm publish" "publish": "npm run test && npm run build && npm publish"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -33,6 +34,7 @@
"chai": "^4.3.6", "chai": "^4.3.6",
"global": "^4.3.2", "global": "^4.3.2",
"mocha": "^9.2.2", "mocha": "^9.2.2",
"process-yargs-parser": "^2.1.0",
"typescript": "^4.6.2" "typescript": "^4.6.2"
}, },
"devDependencies": { "devDependencies": {

View file

@ -58,9 +58,22 @@ export class ScriptExtraction {
* ScriptExtraction.extractScript('s; e // => 1', 0) // => [{tag: 'Statement', stmt: 's;'}, {tag: '==', lhs: 'e', rhs: '1', line: 1}] * ScriptExtraction.extractScript('s; e // => 1', 0) // => [{tag: 'Statement', stmt: 's;'}, {tag: '==', lhs: 'e', rhs: '1', line: 1}]
*/ */
private static extractScript(s: string, linestart: number): Script { private static extractScript(s: string, linestart: number): Script {
function getLineNumber(pos: number) {
let line = 0;
for (let i = 0; i < pos; i++) {
if (s === "\n") {
line++
}
}
return line;
}
const pwoc = ts.createPrinter({removeComments: true}) const pwoc = ts.createPrinter({removeComments: true})
const ast = ts.createSourceFile('_.ts', s, ts.ScriptTarget.Latest) const ast = ts.createSourceFile('_.ts', s, ts.ScriptTarget.Latest)
return ast.statements.map((stmt, i): Statement | Equality => { return ast.statements.map((stmt, i): Statement | Equality => {
if (ts.isExpressionStatement(stmt)) { if (ts.isExpressionStatement(stmt)) {
const next = ast.statements[i + 1] // zip with next const next = ast.statements[i + 1] // zip with next
const [a, z] = next ? [next.pos, next.end] : [stmt.end, ast.end] const [a, z] = next ? [next.pos, next.end] : [stmt.end, ast.end]
@ -69,7 +82,9 @@ export class ScriptExtraction {
if (m && m[1]) { if (m && m[1]) {
const lhs = pwoc.printNode(ts.EmitHint.Expression, stmt.expression, ast) const lhs = pwoc.printNode(ts.EmitHint.Expression, stmt.expression, ast)
const rhs = m[1].trim() const rhs = m[1].trim()
return {tag: '==', lhs, rhs, line: linestart + i}
return {tag: '==', lhs, rhs, line: linestart + getLineNumber(stmt.pos)}
} }
} }

View file

@ -6,6 +6,7 @@ export interface Equality {
tag: '==' tag: '=='
lhs: string lhs: string
rhs: string, rhs: string,
// Line number in the single script
line: number line: number
} }
@ -35,7 +36,7 @@ export default class UnitTest {
return ScriptExtraction.extractScripts(comment).map(({script, line, name}, i) => return ScriptExtraction.extractScripts(comment).map(({script, line, name}, i) =>
new UnitTest(script, { new UnitTest(script, {
...context, ...context,
linenumber: (context.linenumber ?? 0) + line, linenumber: (context.linenumber ?? 0) ,
testname: name ?? 'doctest ' + i testname: name ?? 'doctest ' + i
},imports)) },imports))
} }
@ -62,7 +63,7 @@ export default class UnitTest {
if (s.tag == 'Statement') { if (s.tag == 'Statement') {
return s.stmt return s.stmt
} else { } else {
return `__expect(${s.lhs}, "failed at ${this.context.functionname} (${this.context.filepath}:${s.line}:1)").to.deep.equal(${s.rhs})` return `__expect(${s.lhs}, "failed at ${this.context.functionname} (${this.context.filepath}:${s.line + (this.context.linenumber ?? 0)}:1)").to.deep.equal(${s.rhs})`
} }
}) })
.map(x => '\n ' + x) .map(x => '\n ' + x)

View file

@ -31,28 +31,55 @@ function main() {
console.error("Probably running the testsuite, detects '--require' as second argument. Quitting now") console.error("Probably running the testsuite, detects '--require' as second argument. Quitting now")
return; return;
} }
const argv = require('process-yargs-parser')(process.argv.slice(2), { "duplicate-arguments-array": true})
if (directory === undefined) { if (directory === undefined) {
console.log("Usage: doctest-ts-improved <directory under test>. This will automatically scan recursively for '.ts'-files, excluding 'node_modules' '*.doctest.ts'-files") console.log("Usage: doctest-ts-improved <directory under test> [--ignore regexp]. This will automatically scan recursively for '.ts'-files, excluding 'node_modules' and '*.doctest.ts'-files.")
} }
const files = readDirRecSync(directory) let blacklistPatterns: string | string[] = argv["ignore"]
let files = readDirRecSync(argv._[0])
.filter(p => p.endsWith(".ts")) .filter(p => p.endsWith(".ts"))
.filter(p => p.indexOf("/node_modules/") < 0 && !p.endsWith(".doctest.ts")) .filter(p => p.indexOf("/node_modules/") < 0 && !p.endsWith(".doctest.ts"))
if (blacklistPatterns !== undefined) {
if(typeof blacklistPatterns === "string"){
blacklistPatterns = [blacklistPatterns]
}
const ignored: string[] = []
files = files.filter(p => {
const isIgnored = (<string[]>blacklistPatterns).some(blacklistPattern => p.match(new RegExp(blacklistPattern)) !== null);
if (isIgnored) {
ignored.push(p)
}
return !isIgnored
})
if(argv.verbose){
console.log("Ignored the following files as they match the ignore pattern",blacklistPatterns.join(","),"\n", ignored.join(", "))
}
}
const noTests: string[] = [] const noTests: string[] = []
for (let i = 0; i < files.length; i++){ let totalTests = 0
let totalFilesWithTests = 0
for (let i = 0; i < files.length; i++) {
const file = files[i]; const file = files[i];
process.stdout.write(`\r (${i}/${files.length}) inspecting ${file} \r`) process.stdout.write(`\r (${i}/${files.length}) inspecting ${file} \r`)
const generated = new TestCreator(file).createTest() const generated = new TestCreator(file).createTest()
if (generated === 0) { if (generated === 0) {
noTests.push(file) noTests.push(file)
} else { } else {
totalFilesWithTests++
totalTests += generated
console.log("Generated tests for " + file + " (" + generated + " tests found)") console.log("Generated tests for " + file + " (" + generated + " tests found)")
} }
} }
console.log(`Generated tests for ${totalFilesWithTests} containing ${totalTests} tests in total. ${Math.round(100 * totalFilesWithTests / (totalFilesWithTests + noTests.length))}% of the files have test`)
if (noTests.length > 0) { if (noTests.length > 0) {
const i = Math.round(Math.random() * noTests.length) const i = Math.round(Math.random() * noTests.length)
const randomFile = noTests[i] const randomFile = noTests[i]
console.log(`No tests found in ${noTests.length} files. Why not add a test to ${randomFile}?`) console.log(`No tests found in ${noTests.length} files. We suggest making a test for ${randomFile} - it'll benefit from it?`)
} }
} }

View file

@ -61,24 +61,24 @@ A.x() // => 21 * 2`
expect(scripts.length).eq(3) expect(scripts.length).eq(3)
const [doctest0, doctest1, doctest2shouldEqual] = scripts; const [doctest0, doctest1, doctest2shouldEqual] = scripts;
expect(doctest0).to.deep.eq({ expect(doctest0).to.deep.eq({
script: [{tag: '==', lhs: 'A.x()', rhs: "42", line: 2}], script: [{tag: '==', lhs: 'A.x()', rhs: "42", line: 0}],
name: undefined, name: undefined,
line: 2 line: 2
}) })
expect(doctest1).to.deep.eq({ expect(doctest1).to.deep.eq({
script: [{tag: '==', lhs: 'A.x() + 1', rhs: "43", line: 4}, { script: [{tag: '==', lhs: 'A.x() + 1', rhs: "43", line: 0}, {
tag: '==', tag: '==',
lhs: 'A.x() - 1', lhs: 'A.x() - 1',
rhs: "41", rhs: "41",
line: 5 line: 1
}], }],
name: undefined, name: undefined,
line: 4 line: 4
}) })
expect(doctest2shouldEqual).to.deep.eq({ expect(doctest2shouldEqual).to.deep.eq({
script: [{tag: '==', lhs: 'A.x()', rhs: "21 * 2", line: 7}], script: [{tag: '==', lhs: 'A.x()', rhs: "21 * 2", line: 0}],
name: "should equal 2 * 21", name: "should equal 2 * 21",
line: 7 line: 7
}) })

View file

@ -868,6 +868,11 @@
"resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz" "resolved" "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
"version" "2.0.1" "version" "2.0.1"
"process-yargs-parser@^2.1.0":
"integrity" "sha512-tzMsZn3lKksICtEhICR/k+Qv1UmQNVtzm0FaL10OiGJtw0ixgw0woNefcREDc6ZjqXOKBSruRagyULuwZ4FK4Q=="
"resolved" "https://registry.npmjs.org/process-yargs-parser/-/process-yargs-parser-2.1.0.tgz"
"version" "2.1.0"
"process@^0.11.10": "process@^0.11.10":
"integrity" "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" "integrity" "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
"resolved" "https://registry.npmjs.org/process/-/process-0.11.10.tgz" "resolved" "https://registry.npmjs.org/process/-/process-0.11.10.tgz"