Skip to content

Commit 72f969a

Browse files
committed
parse output from TAP
1 parent a3f3254 commit 72f969a

18 files changed

+235
-149
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ PyTest Python test runner for Atom-CodeRoad.
66

77
Install Python
88

9-
pip install -U pytest
10-
pip install pytest-json
9+
pip install -U pytest
10+
pip install tap.py
1111

1212

1313
### Writing Tests

_report.json

Lines changed: 0 additions & 1 deletion
This file was deleted.

lib/create-runner.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
"use strict";
2-
var path = require('path');
32
var child = require('child_process');
43
function createRunner(config, testFile) {
5-
var report = path.join(__dirname, '..', '_report.json');
64
return child.exec([
7-
'py.test',
8-
("--json=" + report),
5+
'python -m pytest',
6+
'--cache-clear',
97
'-x',
8+
'--tb=no',
9+
'--tap-stream',
1010
testFile
1111
].join(' '), function (error, stdout, stderr) {
12-
console.log("stdout: " + stdout);
13-
console.log("stderr: " + stderr);
1412
if (error !== null) {
1513
console.log("exec error: " + error);
1614
}

lib/parse-tap.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
"use strict";
2+
var isTap = /^# TAP/m;
3+
var finalTestNumber = /^1..([0-9+])$/m;
4+
var testError = /^# E\s+(.+)$/m;
5+
function formatFailureMessage(message) {
6+
return message.split('_').join(' ');
7+
}
8+
function parseTap(data) {
9+
if (!data.match(isTap)) {
10+
console.log('No TAP output');
11+
return;
12+
}
13+
if (!data.match(finalTestNumber)) {
14+
console.log('Could not parse final test number');
15+
return;
16+
}
17+
var finalTest = parseInt(data.match(finalTestNumber)[1], 10);
18+
var final = null;
19+
if (data.match(testError)) {
20+
var failingLineRegex = new RegExp("^not ok " + finalTest + " - (.+)$", 'm');
21+
var line = data.match(failingLineRegex)[1];
22+
var taskPosition = parseInt(line.match(/Test([0-9]+)/)[1], 10);
23+
var message = formatFailureMessage(line.match(/\.test_(.+)$/)[1]);
24+
if (!message) {
25+
console.log('Error with test. There is no valid test message');
26+
message = '';
27+
}
28+
final = {
29+
completed: false,
30+
msg: formatFailureMessage(message),
31+
taskPosition: taskPosition - 1,
32+
timedOut: false
33+
};
34+
}
35+
else {
36+
var finalPassRegex = new RegExp("^ok " + finalTest + " - (.+)$", 'm');
37+
var line = data.match(finalPassRegex)[1];
38+
var taskPosition = parseInt(line.match(/Test([0-9]+)/)[1], 10);
39+
final = {
40+
completed: true,
41+
msg: "Task " + taskPosition + " Complete",
42+
taskPosition: taskPosition
43+
};
44+
}
45+
return final;
46+
}
47+
Object.defineProperty(exports, "__esModule", { value: true });
48+
exports.default = parseTap;

lib/runner.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,13 @@
11
"use strict";
2-
var path = require('path');
3-
var exists_1 = require('./exists');
42
var create_runner_1 = require('./create-runner');
5-
var parse_json_1 = require('./parse-json');
6-
var pathToResults = path.resolve(__dirname, '..', '_report.json');
3+
var parse_tap_1 = require('./parse-tap');
74
function runner(testFile, config, handleResult) {
85
var runner = create_runner_1.default(config, testFile);
96
var final = null;
107
return new Promise(function (resolve, reject) {
118
runner.stdout.on('data', function (data) {
129
data = data.toString();
13-
console.log(data);
14-
if (!exists_1.default(pathToResults)) {
15-
console.log('error finding test output file: ', data);
16-
return;
17-
}
18-
final = parse_json_1.default(pathToResults);
10+
final = parse_tap_1.default(data);
1911
final.change = final.taskPosition - config.taskPosition;
2012
final.pass = final.change > 0;
2113
handleResult(final);

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
"source": [
3838
"test/*.spec.js"
3939
],
40-
"failFast": true
40+
"failFast": false,
41+
"serial": true,
42+
"noCache": true
4143
}
4244
}

src/create-runner.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
import * as path from 'path';
21
const child = require('child_process');
32

43
export default function createRunner(config: CR.Config, testFile: string) {
54

6-
let report = path.join(__dirname, '..', '_report.json');
7-
85
return child.exec([
9-
'py.test',
10-
`--json=${report}`,
6+
'python -m pytest',
7+
'--cache-clear',
118
'-x', // stop after first failure
9+
'--tb=no', // no traceback
10+
'--tap-stream',
1211
testFile
1312
].join(' '), (error, stdout, stderr) => {
14-
console.log(`stdout: ${stdout}`);
15-
console.log(`stderr: ${stderr}`);
13+
// console.log(`stdout: ${stdout}`);
14+
// console.log(`stderr: ${stderr}`);
1615
if (error !== null) {
1716
console.log(`exec error: ${error}`);
1817
}

src/parse-json.ts

Lines changed: 0 additions & 56 deletions
This file was deleted.

src/parse-tap.ts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
const isTap = /^# TAP/m;
2+
const finalTestNumber = /^1..([0-9+])$/m;
3+
const testError = /^# E\s+(.+)$/m;
4+
5+
function formatFailureMessage(message: string): string {
6+
return message.split('_').join(' ');
7+
}
8+
9+
export default function parseTap(data: string): ParseFinal {
10+
if (!data.match(isTap)) {
11+
console.log('No TAP output');
12+
return;
13+
}
14+
15+
if (!data.match(finalTestNumber)) {
16+
console.log('Could not parse final test number');
17+
return;
18+
}
19+
let finalTest: number = parseInt(data.match(finalTestNumber)[1], 10);
20+
21+
let final: ParseFinal = null;
22+
23+
if (data.match(testError)) {
24+
25+
// fail
26+
27+
let failingLineRegex = new RegExp(`^not ok ${finalTest} - (.+)$`, 'm');
28+
let line: string = data.match(failingLineRegex)[1];
29+
let taskPosition: number = parseInt(line.match(/Test([0-9]+)/)[1], 10);
30+
let message: string = formatFailureMessage(line.match(/\.test_(.+)$/)[1]);
31+
32+
if (!message) {
33+
console.log('Error with test. There is no valid test message');
34+
message = '';
35+
}
36+
37+
final = {
38+
completed: false,
39+
msg: formatFailureMessage(message),
40+
taskPosition: taskPosition - 1,
41+
timedOut: false // TODO
42+
};
43+
} else {
44+
45+
// all pass
46+
47+
let finalPassRegex = new RegExp(`^ok ${finalTest} - (.+)$`, 'm');
48+
let line: string = data.match(finalPassRegex)[1];
49+
let taskPosition: number = parseInt(line.match(/Test([0-9]+)/)[1], 10);
50+
51+
final = {
52+
completed: true,
53+
msg: `Task ${taskPosition} Complete`,
54+
taskPosition
55+
};
56+
}
57+
58+
return final;
59+
}

src/runner.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,31 @@
11
import * as path from 'path';
2+
import * as fs from 'fs';
23
import exists from './exists';
34
import createRunner from './create-runner';
4-
import parseJson from './parse-json';
5-
6-
const pathToResults = path.resolve(__dirname, '..', '_report.json');
5+
import parseTap from './parse-tap';
76

87
export default function runner(testFile: string, config: CR.Config,
98
handleResult: (result) => CR.TestResult) {
109

10+
11+
// cleanup .json file
1112
let runner = createRunner(config, testFile);
1213
var final = null;
1314

1415
return new Promise((resolve, reject) => {
1516
runner.stdout.on('data', function(data): void {
1617

1718
data = data.toString();
18-
console.log(data);
19-
20-
if (!exists(pathToResults)) {
21-
console.log('error finding test output file: ', data);
22-
return;
23-
}
19+
// console.log('DATA', data);
2420

2521
// transform data;
26-
final = parseJson(pathToResults);
22+
final = parseTap(data);
2723
final.change = final.taskPosition - config.taskPosition;
2824
final.pass = final.change > 0;
2925

3026
// return result to atom-coderoad
3127
handleResult(final);
28+
3229
});
3330

3431
runner.stderr.on('data', function(data) {

test/demos/fail-at-one.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ def test_failing_test(self):
88
assert a > 2
99

1010
class Test02Class:
11-
def test_passing_one(self):
11+
def test_passing_two(self):
1212
assert a == 1
1313

1414
def test_passing_test(self):
1515
assert a < 2
1616

1717
class Test03Class:
18-
def test_passing_one(self):
18+
def test_passing_three(self):
1919
assert a == 1
2020

2121
def test_passing_test(self):

test/demos/fail-at-three.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ def test_passing_test(self):
88
assert a < 2
99

1010
class Test02Class:
11-
def test_passing_one(self):
11+
def test_passing_two(self):
1212
assert a == 1
1313

1414
def test_passing_test(self):
1515
assert a < 2
1616

1717
class Test03Class:
18-
def test_passing_one(self):
18+
def test_passing_three(self):
1919
assert a == 1
2020

2121
def test_failing_test(self):

test/demos/pass-three.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ def test_passing_test(self):
88
assert a < 2
99

1010
class Test02Class:
11-
def test_passing_one(self):
11+
def test_passing_two(self):
1212
assert a == 1
1313

1414
def test_passing_test(self):
1515
assert a < 2
1616

1717
class Test03Class:
18-
def test_passing_one(self):
18+
def test_passing_three(self):
1919
assert a == 1
2020

2121
def test_passing_test(self):

test/demos/single-test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
a = 1;
22

33
class Test01Class:
4-
def test_passing_one(self):
4+
def test_single_test(self):
55
assert a == 1

0 commit comments

Comments
 (0)