11/* eslint-disable @typescript-eslint/no-unsafe-argument */
22import assert from 'assert' ;
3+ import { EOL } from 'os' ;
4+ import path from 'path' ;
35import { anything , instance , mock , reset , spy , when } from 'ts-mockito' ;
4- import {
5- commands ,
6- TestItem ,
7- TestItemCollection ,
8- TestMessage ,
9- TestRun ,
10- Uri ,
11- workspace ,
12- } from 'vscode' ;
6+ import { TestItem , TestItemCollection , TestMessage , TestRun , Uri , workspace } from 'vscode' ;
137import { CancellationTokenSource } from 'vscode-languageclient' ;
148import * as e3 from '../../src/e3Testsuite' ;
159import { activate } from '../utils' ;
@@ -69,127 +63,161 @@ suite('e3-testsuite', function () {
6963
7064 test ( 'Test list after run' , async function ( ) {
7165 await e3 . controller . refreshHandler ! ( new CancellationTokenSource ( ) . token ) ;
72- await commands . executeCommand ( 'testing.runAll' ) ;
7366
74- assert . deepStrictEqual ( toTestResult ( e3 . controller . items ) , [
75- {
76- id : Uri . joinPath ( workspace . workspaceFolders ! [ 0 ] . uri , 'testsuite.py' ) . toString ( ) ,
77- label : 'testsuite.py' ,
78- children : [
79- {
80- id : '01-test-one-result' ,
81- label : '01-test-one-result' ,
82- children : [ ] ,
83- } ,
84- {
85- id : '02-test-multiple-results' ,
86- label : '02-test-multiple-results' ,
87- /**
88- * We expect these sub-results to appear after the test run
89- */
90- children : [
91- {
92- id : '02-test-multiple-results.sub3' ,
93- label : '02-test-multiple-results.sub3' ,
94- children : [ ] ,
95- } ,
96- {
97- id : '02-test-multiple-results.sub2' ,
98- label : '02-test-multiple-results.sub2' ,
99- children : [ ] ,
100- } ,
101- {
102- id : '02-test-multiple-results.sub1' ,
103- label : '02-test-multiple-results.sub1' ,
104- children : [ ] ,
105- } ,
106- ] ,
107- } ,
108- {
109- id : '03-test-multiple-passing-results' ,
110- label : '03-test-multiple-passing-results' ,
111- /**
112- * We expect these sub-results to appear after the test run
113- */
114- children : [
115- {
116- id : '03-test-multiple-passing-results.sub3' ,
117- label : '03-test-multiple-passing-results.sub3' ,
118- children : [ ] ,
119- } ,
120- {
121- id : '03-test-multiple-passing-results.sub2' ,
122- label : '03-test-multiple-passing-results.sub2' ,
123- children : [ ] ,
124- } ,
125- {
126- id : '03-test-multiple-passing-results.sub1' ,
127- label : '03-test-multiple-passing-results.sub1' ,
128- children : [ ] ,
129- } ,
130- ] ,
131- } ,
132- {
133- id : '04-test-only-passing-sub-results' ,
134- label : '04-test-only-passing-sub-results' ,
135- /**
136- * We expect these sub-results to appear after the test run
137- */
138- children : [
139- {
140- id : '04-test-only-passing-sub-results.sub3' ,
141- label : '04-test-only-passing-sub-results.sub3' ,
142- children : [ ] ,
143- } ,
144- {
145- id : '04-test-only-passing-sub-results.sub2' ,
146- label : '04-test-only-passing-sub-results.sub2' ,
147- children : [ ] ,
148- } ,
149- {
150- id : '04-test-only-passing-sub-results.sub1' ,
151- label : '04-test-only-passing-sub-results.sub1' ,
152- children : [ ] ,
153- } ,
154- ] ,
155- } ,
156- {
157- id : '05-test-only-sub-results-one-failing' ,
158- label : '05-test-only-sub-results-one-failing' ,
159- /**
160- * We expect these sub-results to appear after the test run
161- */
162- children : [
163- {
164- id : '05-test-only-sub-results-one-failing.sub3' ,
165- label : '05-test-only-sub-results-one-failing.sub3' ,
166- children : [ ] ,
167- } ,
168- {
169- id : '05-test-only-sub-results-one-failing.sub2' ,
170- label : '05-test-only-sub-results-one-failing.sub2' ,
171- children : [ ] ,
172- } ,
173- {
174- id : '05-test-only-sub-results-one-failing.sub1' ,
175- label : '05-test-only-sub-results-one-failing.sub1' ,
176- children : [ ] ,
177- } ,
178- ] ,
179- } ,
180- {
181- id : '06-test-with-diff' ,
182- label : '06-test-with-diff' ,
183- children : [ ] ,
184- } ,
185- {
186- id : '07-test-with-no-results' ,
187- label : '07-test-with-no-results' ,
188- children : [ ] ,
189- } ,
190- ] ,
191- } ,
192- ] ) ;
67+ const spyCtrl = spy ( e3 . controller ) ;
68+ try {
69+ const mockRun = mock < TestRun > ( ) ;
70+ let consoleOutput = '' ;
71+ when ( mockRun . appendOutput ( anything ( ) ) ) . thenCall ( ( output : string ) => {
72+ consoleOutput += output . replace ( / ( \r + \n | \n \r + ) / g, '\n' ) ;
73+ } ) ;
74+
75+ const run = instance ( mockRun ) ;
76+
77+ when ( spyCtrl . createTestRun ( anything ( ) ) ) . thenReturn ( run ) ;
78+ when ( spyCtrl . createTestRun ( anything ( ) , anything ( ) ) ) . thenReturn ( run ) ;
79+ when ( spyCtrl . createTestRun ( anything ( ) , anything ( ) , anything ( ) ) ) . thenReturn ( run ) ;
80+
81+ await e3 . runHandler (
82+ { include : undefined , exclude : undefined , profile : undefined } ,
83+ new CancellationTokenSource ( ) . token ,
84+ ) ;
85+
86+ const expectedResult = [
87+ {
88+ id : Uri . joinPath ( workspace . workspaceFolders ! [ 0 ] . uri , 'testsuite.py' ) . toString ( ) ,
89+ label : 'testsuite.py' ,
90+ children : [
91+ {
92+ id : '01-test-one-result' ,
93+ label : '01-test-one-result' ,
94+ children : [ ] ,
95+ } ,
96+ {
97+ id : '02-test-multiple-results' ,
98+ label : '02-test-multiple-results' ,
99+ /**
100+ * We expect these sub-results to appear after the test run
101+ */
102+ children : [
103+ {
104+ id : '02-test-multiple-results.sub3' ,
105+ label : '02-test-multiple-results.sub3' ,
106+ children : [ ] ,
107+ } ,
108+ {
109+ id : '02-test-multiple-results.sub2' ,
110+ label : '02-test-multiple-results.sub2' ,
111+ children : [ ] ,
112+ } ,
113+ {
114+ id : '02-test-multiple-results.sub1' ,
115+ label : '02-test-multiple-results.sub1' ,
116+ children : [ ] ,
117+ } ,
118+ ] ,
119+ } ,
120+ {
121+ id : '03-test-multiple-passing-results' ,
122+ label : '03-test-multiple-passing-results' ,
123+ /**
124+ * We expect these sub-results to appear after the test run
125+ */
126+ children : [
127+ {
128+ id : '03-test-multiple-passing-results.sub3' ,
129+ label : '03-test-multiple-passing-results.sub3' ,
130+ children : [ ] ,
131+ } ,
132+ {
133+ id : '03-test-multiple-passing-results.sub2' ,
134+ label : '03-test-multiple-passing-results.sub2' ,
135+ children : [ ] ,
136+ } ,
137+ {
138+ id : '03-test-multiple-passing-results.sub1' ,
139+ label : '03-test-multiple-passing-results.sub1' ,
140+ children : [ ] ,
141+ } ,
142+ ] ,
143+ } ,
144+ {
145+ id : '04-test-only-passing-sub-results' ,
146+ label : '04-test-only-passing-sub-results' ,
147+ /**
148+ * We expect these sub-results to appear after the test run
149+ */
150+ children : [
151+ {
152+ id : '04-test-only-passing-sub-results.sub3' ,
153+ label : '04-test-only-passing-sub-results.sub3' ,
154+ children : [ ] ,
155+ } ,
156+ {
157+ id : '04-test-only-passing-sub-results.sub2' ,
158+ label : '04-test-only-passing-sub-results.sub2' ,
159+ children : [ ] ,
160+ } ,
161+ {
162+ id : '04-test-only-passing-sub-results.sub1' ,
163+ label : '04-test-only-passing-sub-results.sub1' ,
164+ children : [ ] ,
165+ } ,
166+ ] ,
167+ } ,
168+ {
169+ id : '05-test-only-sub-results-one-failing' ,
170+ label : '05-test-only-sub-results-one-failing' ,
171+ /**
172+ * We expect these sub-results to appear after the test run
173+ */
174+ children : [
175+ {
176+ id : '05-test-only-sub-results-one-failing.sub3' ,
177+ label : '05-test-only-sub-results-one-failing.sub3' ,
178+ children : [ ] ,
179+ } ,
180+ {
181+ id : '05-test-only-sub-results-one-failing.sub2' ,
182+ label : '05-test-only-sub-results-one-failing.sub2' ,
183+ children : [ ] ,
184+ } ,
185+ {
186+ id : '05-test-only-sub-results-one-failing.sub1' ,
187+ label : '05-test-only-sub-results-one-failing.sub1' ,
188+ children : [ ] ,
189+ } ,
190+ ] ,
191+ } ,
192+ {
193+ id : '06-test-with-diff' ,
194+ label : '06-test-with-diff' ,
195+ children : [ ] ,
196+ } ,
197+ {
198+ id : '07-test-with-no-results' ,
199+ label : '07-test-with-no-results' ,
200+ children : [ ] ,
201+ } ,
202+ ] ,
203+ } ,
204+ ] ;
205+
206+ const actualResult = toTestResult ( e3 . controller . items ) ;
207+
208+ try {
209+ assert . deepStrictEqual ( actualResult , expectedResult ) ;
210+ } catch ( error ) {
211+ // Include console output in the error message for debugging
212+ const errorMessage =
213+ `Test structure assertion failed.\n\n` +
214+ `Console output:\n${ consoleOutput } \n\n` +
215+ `Original error:\n${ String ( error ) } ` ;
216+ throw new Error ( errorMessage ) ;
217+ }
218+ } finally {
219+ reset ( spyCtrl ) ;
220+ }
193221 } ) ;
194222
195223 test ( 'Capturing test results' , async function ( ) {
@@ -253,19 +281,23 @@ suite('e3-testsuite', function () {
253281 ) ;
254282
255283 const workspaceRoot = workspace . workspaceFolders ! [ 0 ] . uri . fsPath ;
256- const testsuitePath = `${ workspaceRoot } / testsuite.py` ;
284+ const testsuitePath = `${ workspaceRoot } ${ path . sep } testsuite.py` ;
257285 const pythonPathRegex =
258- / R u n n i n g : " ( .+ p y t h o n ) " " .+ t e s t s u i t e \. p y " " - - f a i l u r e - e x i t - c o d e = 0 " \n / ;
286+ / R u n n i n g : " ( .* p y t h o n ) " " .+ t e s t s u i t e \. p y " " - - f a i l u r e - e x i t - c o d e = 0 " / ;
259287
260288 // Extract the python path from the output
261289 const pythonMatch = consoleOutput . match ( pythonPathRegex ) ;
262- assert . ok ( pythonMatch , ' Python path not found in console output' ) ;
290+ assert . ok ( pythonMatch , ` Python path not found in console output: ${ consoleOutput } ` ) ;
263291 const pythonPath = pythonMatch [ 1 ] ;
264292
265293 // Check that the console output contains the expected command and results
266294 const expectedCommand =
267295 `Running: "${ pythonPath } " "${ testsuitePath } " ` + '"--failure-exit-code=0"' ;
268- assert . ok ( consoleOutput . includes ( expectedCommand ) , 'Expected command not found' ) ;
296+ assert . ok (
297+ consoleOutput . includes ( expectedCommand ) ,
298+ `Expected command '${ expectedCommand } ' not` +
299+ ` found in console output: ${ consoleOutput } ` ,
300+ ) ;
269301
270302 // Check for expected test results (order-independent)
271303 const expectedResults = [
@@ -288,12 +320,18 @@ suite('e3-testsuite', function () {
288320 ] ;
289321
290322 for ( const result of expectedResults ) {
291- assert . ok ( consoleOutput . includes ( result ) , `Expected result not found: ${ result } ` ) ;
323+ assert . ok (
324+ consoleOutput . includes ( result ) ,
325+ `Expected result not found: ${ result } \nActual console output: ${ consoleOutput } ` ,
326+ ) ;
292327 }
293328
294329 // Check for the summary section
295330 const expectedSummary = 'INFO Summary:\n PASS 12\n FAIL 4' ;
296- assert . ok ( consoleOutput . includes ( expectedSummary ) , 'Expected summary not found' ) ;
331+ assert . ok (
332+ consoleOutput . includes ( expectedSummary ) ,
333+ `Expected summary not found in console output: ${ consoleOutput } ` ,
334+ ) ;
297335
298336 assert . deepStrictEqual ( enqueued . sort ( ) , [
299337 '01-test-one-result' ,
@@ -347,7 +385,7 @@ suite('e3-testsuite', function () {
347385 } ,
348386 {
349387 id : '02-test-multiple-results.sub3' ,
350- message : [ { message : ' Failure message\n\nLong\ nExecution\nLog' } ] ,
388+ message : [ { message : ` Failure message${ EOL + EOL } Long\ nExecution\nLog` } ] ,
351389 } ,
352390 {
353391 id : '05-test-only-sub-results-one-failing.sub2' ,
@@ -361,7 +399,7 @@ suite('e3-testsuite', function () {
361399 actualOutput : 'Actual\nOutput\nText' ,
362400 expectedOutput : 'Expected\nOutput\nText content' ,
363401 } ,
364- { message : ' Test Log\nLong\ nExecution\nLog' } ,
402+ { message : ` Test Log${ EOL } Long\ nExecution\nLog` } ,
365403 ] ,
366404 } ,
367405 ] ) ;
0 commit comments