Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc35d736

Browse files
committed
Merge pull requestcoderoad#184 from ShMcK/feature/test-parser
Feature/test parser
2 parentsc176913 +e358c41 commitc35d736

File tree

5 files changed

+170
-44
lines changed

5 files changed

+170
-44
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import{ParserOutput,Fail}from'./parser'
2+
3+
// TODO: implement better success ouput
4+
// export const formatSuccessOutput = (tap: ParserOutput): string => {}
5+
6+
exportconstformatFailOutput=(tap:ParserOutput):string=>{
7+
letoutput=`'TESTS FAILED\n`
8+
tap.failed.forEach((fail:Fail)=>{
9+
constdetails=fail.details ?`\n${fail.details}\n\n` :''
10+
output+=` ✘${fail.message}\n${details}`
11+
})
12+
returnoutput
13+
}

‎src/services/testRunner/index.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import parser from './parser'
44
import{debounce,throttle}from'./throttle'
55
importonErrorfrom'../sentry/onError'
66
import{clearOutput,displayOutput}from'./output'
7+
import{formatFailOutput}from'./formatOutput'
78

89
exportinterfacePayload{
910
stepId:string
@@ -52,11 +53,12 @@ const createTestRunner = (config: TestRunnerConfig, callbacks: Callbacks) => {
5253

5354
consttap=parser(stdout||'')
5455
if(stderr){
55-
//failures also trigger stderr
56+
//FAIL also trigger stderr
5657
if(stdout&&stdout.length&&!tap.ok){
57-
constmessage=tap.message ?tap.message :''
58-
callbacks.onFail(payload,message)
59-
displayOutput(stdout)
58+
constfirstFailMessage=tap.failed[0].message
59+
callbacks.onFail(payload,firstFailMessage)
60+
constoutput=formatFailOutput(tap)
61+
displayOutput(output)
6062
return
6163
}else{
6264
callbacks.onError(payload)
@@ -66,7 +68,7 @@ const createTestRunner = (config: TestRunnerConfig, callbacks: Callbacks) => {
6668
}
6769
}
6870

69-
//success!
71+
//PASS
7072
if(tap.ok){
7173
clearOutput()
7274
callbacks.onSuccess(payload)

‎src/services/testRunner/output.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,11 @@ const getOutputChannel = (name: string): vscode.OutputChannel => {
1111

1212
constoutputChannelName='CodeRoad Output'
1313

14-
constparseOutput=(text:string):string=>{
15-
letresult=''
16-
for(constlineoftext.split(/\r?\n/)){
17-
if(line.match(/^#/)||line.match(/^notok/)){
18-
result+=line+'\n'
19-
}
20-
}
21-
returnresult
22-
}
23-
2414
exportconstdisplayOutput=(text:string)=>{
2515
constchannel=getOutputChannel(outputChannelName)
2616
channel.clear()
2717
channel.show(true)
28-
constoutput=parseOutput(text)
29-
channel.append(output)
18+
channel.append(text)
3019
}
3120

3221
exportconstclearOutput=()=>{

‎src/services/testRunner/parser.test.ts

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
importparserfrom'./parser'
22

33
describe('parser',()=>{
4-
test('shoulddetect success',()=>{
4+
test('shouldpass single success',()=>{
55
constexample=`
6-
1..2
6+
1..1
77
ok 1 - Should pass
8-
ok 2 - Should also pass
98
`
10-
expect(parser(example)).toEqual({ok:true})
9+
expect(parser(example)).toEqual({ok:true,passed:[{message:'Should pass'}],failed:[]})
1110
})
12-
test('should detectfailure',()=>{
11+
test('should detectmultiple successes',()=>{
1312
constexample=`
14-
1..3
13+
1..2
1514
ok 1 - Should pass
16-
not ok 2 - This one fails
17-
ok 3 - Also passes
15+
ok 2 - Should also pass
1816
`
19-
expect(parser(example).ok).toBe(false)
17+
constresult=parser(example)
18+
expect(result).toEqual({
19+
ok:true,
20+
passed:[{message:'Should pass'},{message:'Should also pass'}],
21+
failed:[],
22+
})
2023
})
2124
test('should detect failure if no tests passed',()=>{
2225
constexample=`
@@ -26,6 +29,15 @@ ok 3 - Also passes
2629
# FAIL __tests__/sum.test.js
2730
2831
not ok 1 ● sum › should add two numbers together
32+
`
33+
expect(parser(example).ok).toBe(false)
34+
})
35+
test('should detect single failure among successes',()=>{
36+
constexample=`
37+
1..3
38+
ok 1 - Should pass
39+
not ok 2 - This one fails
40+
ok 3 - Also passes
2941
`
3042
expect(parser(example).ok).toBe(false)
3143
})
@@ -37,7 +49,7 @@ not ok 2 - First to fail
3749
ok 3 - Also passes
3850
not ok 4 - Second to fail
3951
`
40-
expect(parser(example).message).toBe('First to fail')
52+
expect(parser(example).failed).toEqual([{message:'First to fail'},{message:'Second to fail'}])
4153
})
4254

4355
test('should parse mocha tap example',()=>{
@@ -65,6 +77,68 @@ ok 3 sumItems should total numbers accurately
6577
# fail 1
6678
# skip 0
6779
`
68-
expect(parser(example).message).toBe("sumItems shouldn't return NaN")
80+
expect(parser(example).failed).toEqual([{message:"sumItems shouldn't return NaN"}])
81+
})
82+
test('should capture single error details',()=>{
83+
constexample=`
84+
not ok 1 package.json should have a valid "author" key
85+
# AssertionError [ERR_ASSERTION]: no "author" key provided
86+
# at Context.<anonymous> (test/packagejson.test.js:11:12)
87+
# at processImmediate (internal/timers.js:439:21)
88+
# tests 1
89+
# pass 0
90+
# fail 1
91+
# skip 0
92+
`
93+
constresult=parser(example)
94+
expect(result.failed[0].message).toBe('package.json should have a valid "author" key')
95+
expect(result.failed[0].details).toBe(`AssertionError [ERR_ASSERTION]: no "author" key provided
96+
at Context.<anonymous> (test/packagejson.test.js:11:12)
97+
at processImmediate (internal/timers.js:439:21)`)
98+
})
99+
test('should capture multiple error details',()=>{
100+
constexample=`
101+
not ok 1 package.json should have a valid "author" key
102+
# AssertionError [ERR_ASSERTION]: no "author" key provided
103+
# at Context.<anonymous> (test/packagejson.test.js:11:12)
104+
# at processImmediate (internal/timers.js:439:21)
105+
not ok 2 package.json should have a valid "description" key
106+
# AssertionError [ERR_ASSERTION]: no "description" key provided
107+
# tests 1
108+
# pass 0
109+
# fail 1
110+
# skip 0
111+
`
112+
constresult=parser(example)
113+
expect(result.failed[0].message).toBe('package.json should have a valid "author" key')
114+
expect(result.failed[0].details).toBe(`AssertionError [ERR_ASSERTION]: no "author" key provided
115+
at Context.<anonymous> (test/packagejson.test.js:11:12)
116+
at processImmediate (internal/timers.js:439:21)`)
117+
expect(result.failed[1].message).toBe('package.json should have a valid "description" key')
118+
expect(result.failed[1].details).toBe(`AssertionError [ERR_ASSERTION]: no "description" key provided`)
119+
})
120+
test('should capture multiple error details between successes',()=>{
121+
constexample=`
122+
ok 1 first passing test
123+
not ok 2 package.json should have a valid "author" key
124+
# AssertionError [ERR_ASSERTION]: no "author" key provided
125+
# at Context.<anonymous> (test/packagejson.test.js:11:12)
126+
# at processImmediate (internal/timers.js:439:21)
127+
ok 3 some passing test
128+
not ok 4 package.json should have a valid "description" key
129+
# AssertionError [ERR_ASSERTION]: no "description" key provided
130+
ok 5 some passing test
131+
# tests 1
132+
# pass 0
133+
# fail 1
134+
# skip 0
135+
`
136+
constresult=parser(example)
137+
expect(result.failed[0].message).toBe('package.json should have a valid "author" key')
138+
expect(result.failed[0].details).toBe(`AssertionError [ERR_ASSERTION]: no "author" key provided
139+
at Context.<anonymous> (test/packagejson.test.js:11:12)
140+
at processImmediate (internal/timers.js:439:21)`)
141+
expect(result.failed[1].message).toBe('package.json should have a valid "description" key')
142+
expect(result.failed[1].details).toBe(`AssertionError [ERR_ASSERTION]: no "description" key provided`)
69143
})
70144
})

‎src/services/testRunner/parser.ts

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,77 @@
1-
interfaceParserOutput{
1+
exportinterfaceFail{
2+
message:string
3+
details?:string
4+
}
5+
6+
exportinterfaceParserOutput{
27
ok:boolean
3-
message?:string
8+
passed:Array<{message:string}>
9+
failed:Array<Fail>
410
}
511

6-
constfail=/^notok\d+\s(\-\s)?(.+)+$/
7-
constok=/^ok/
12+
constr={
13+
fail:/^notok\d+\s(\-\s)?(.+)+$/,
14+
pass:/^ok\d+\s(\-\s)?(.+)+$/,
15+
details:/^#\s{2}(.+)$/,
16+
}
17+
18+
constdetect=(type:'fail'|'pass'|'details',text:string)=>r[type].exec(text)
819

920
constparser=(text:string):ParserOutput=>{
1021
constlines=text.split('\n')
11-
lethasPass=false
22+
23+
constresult:ParserOutput={
24+
ok:true,
25+
passed:[],
26+
failed:[],
27+
}
28+
29+
// temporary holder of error detail strings
30+
letcurrentDetails:string|null=null
31+
32+
constaddCurrentDetails=()=>{
33+
constfailLength:number=result.failed.length
34+
if(currentDetails&&!!failLength){
35+
result.failed[failLength-1].details=currentDetails
36+
currentDetails=null
37+
}
38+
}
39+
1240
for(constlineoflines){
13-
if(line.length){
14-
// parse failed test
15-
constfailRegex=fail.exec(line)
16-
if(!!failRegex){
17-
return{ok:false,message:failRegex[2]}
18-
}
19-
if(!hasPass){
20-
if(!!ok.exec(line)){
21-
hasPass=true
22-
}
41+
if(!line.length){
42+
continue
43+
}
44+
// be optimistic! check for success
45+
constisPass=detect('pass',line)
46+
if(!!isPass){
47+
result.passed.push({message:isPass[2].trim()})
48+
addCurrentDetails()
49+
continue
50+
}
51+
52+
// check for failure
53+
constisFail=detect('fail',line)
54+
if(!!isFail){
55+
result.ok=false
56+
addCurrentDetails()
57+
result.failed.push({message:isFail[2].trim()})
58+
continue
59+
}
60+
61+
// check for error details
62+
constisDetails=detect('details',line)
63+
if(!!isDetails){
64+
constlineDetails:string=isDetails[1].trim()
65+
if(!currentDetails){
66+
currentDetails=lineDetails
67+
}else{
68+
//@ts-ignore ignore as it must be a string
69+
currentDetails+=`\n${lineDetails}`
2370
}
2471
}
2572
}
26-
return{ok:hasPass}
73+
addCurrentDetails()
74+
returnresult
2775
}
2876

2977
exportdefaultparser

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp