Add --ignore as option
This commit is contained in:
parent
c21c4e2b0b
commit
09dfb13a07
7 changed files with 77 additions and 16 deletions
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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": {
|
||||||
|
|
|
@ -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)}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
35
src/main.ts
35
src/main.ts
|
@ -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?`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
|
|
|
@ -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"
|
||||||
|
|
Loading…
Add table
Reference in a new issue