Search code examples
unit-testingphpstormcode-coveragesinonjs-test-driver

How to stop Code Coverage from crashing because of sinon even though tests without code coverage pass?


Issue: code coverage not working when sinon is a dependency.

I currently have 3 test files. Running all the tests lead to 17 tests passing and 0 failing. 2 of these files require extra dependencies (lets call these files testDates.test.js and testButtons.test.js) that the 3rd doesn't need. These include JQuery, Sinon (v7.3.2), and D3.

Running the tests for the 3rd file has 9 tests pass and 0 failing. Running code coverage returns 78% code coverage (this is fine as the functions not being tested are just functions returning hard coded data as a placeholder for actual data retrieval which will be done in the future).

The jsTestDriver.jstd that returns this code coverage are:

 load:

   - allCharts.js

 test:

  - tests/Functional/javascriptTests/actionsTestAllChartsFunctions.test.js

 timeout: 60

(^ actual required files)

load:

  - allCharts.js

  - tests/dependencies/jquery.js

test:

  - tests/Functional/javascriptTests/actionsTestAllChartsFunctions.test.js

timeout: 60

(^ checking if jquery is the issue with code coverage, it isn't)

load:

  - allCharts.js

  - tests/dependencies/jquery.js

  - tests/dependencies/sinon732.js

test:

   - tests/Functional/javascriptTests/actionsTestAllChartsFunctions.test.js

timeout: 60

(^ checking if sinon is the issue with code coverage, it is)

The last try returned the error messages:

com.google.jstestdriver.coverage.CodeInstrumentor$InstrumentationException: error instrumenting C:\Users\smazor\PhpstormProjects\project1\tests\dependencies\sinon732.jsline 179:4 mismatched input 'const' expecting RBRACE
line 1022:12 no viable alternative at input 'throws'
line 1236:13 mismatched input 'throws' expecting Identifier
line 1236:31 extraneous input 'throws' expecting LPAREN
line 3998:12 no viable alternative at input 'function'
line 4992:12 mismatched input 'function' expecting RBRACE
line 4992:20 mismatched input ':' expecting Identifier
line 4992:30 extraneous input '(' expecting Identifier
line 4992:54 no viable alternative at input ')'
line 4993:36 missing RPAREN at ';'
line 4996:18 mismatched input ':' expecting RPAREN
line 4996:28 extraneous input '(' expecting Identifier

Can't execute test due to unknown reason.
Exception in thread "main" 
Can't execute test due to unknown reason.

Can't execute test due to unknown reason.

Can't execute test due to unknown reason.

at com.google.jstestdriver.coverage.CodeInstrumentor.instrument(CodeInstrumentor.java:74)
at com.google.jstestdriver.coverage.CoverageInstrumentingProcessor.process(CoverageInstrumentingProcessor.java:62)
at com.google.jstestdriver.ProcessingFileLoader.postProcessFile(ProcessingFileLoader.java:78)
at com.google.jstestdriver.ProcessingFileLoader.loadFiles(ProcessingFileLoader.java:67)
at com.google.jstestdriver.model.JstdTestCaseDelta.loadFiles(JstdTestCaseDelta.java:59)
at com.google.jstestdriver.FileUploader.uploadToServer(FileUploader.java:218)
at com.google.jstestdriver.action.UploadAction.run(UploadAction.java:39)
at com.google.jstestdriver.ActionRunner.runActions(ActionRunner.java:81)
at com.google.jstestdriver.embedded.JsTestDriverImpl.runConfigurationWithFlags(JsTestDriverImpl.java:342)
at com.google.jstestdriver.embedded.JsTestDriverImpl.runConfiguration(JsTestDriverImpl.java:233)
at com.google.jstestdriver.idea.rt.TestRunner.runTests(TestRunner.java:195)
at com.google.jstestdriver.idea.rt.TestRunner.executeTests(TestRunner.java:96)
at com.google.jstestdriver.idea.rt.TestRunner.executeAll(TestRunner.java:83)
at com.google.jstestdriver.idea.rt.TestRunner.main(TestRunner.java:276)
Caused by: java.lang.IllegalArgumentException: replace: range invalid: 43095..43093(size=371669)
at org.antlr.runtime.TokenRewriteStream.replace(TokenRewriteStream.java:263)
at org.antlr.runtime.TokenRewriteStream.replace(TokenRewriteStream.java:250)
at com.google.jstestdriver.coverage.es3.ES3InstrumentParser.statement(ES3InstrumentParser.java:4107)
at com.google.jstestdriver.coverage.es3.ES3InstrumentParser.sourceElement(ES3InstrumentParser.java:6693)
at com.google.jstestdriver.coverage.es3.ES3InstrumentParser.functionBody(ES3InstrumentParser.java:6531)
at com.google.jstestdriver.coverage.es3.ES3InstrumentParser.functionDeclaration(ES3InstrumentParser.java:6318)
at com.google.jstestdriver.coverage.es3.ES3InstrumentParser.sourceElement(ES3InstrumentParser.java:6682)
at com.google.jstestdriver.coverage.es3.ES3InstrumentParser.program(ES3InstrumentParser.java:6612)
at com.google.jstestdriver.coverage.CodeInstrumentor.instrument(CodeInstrumentor.java:72)
... 13 more

Process finished with exit code 1

and did not generate a code coverage

I am running this on PHPStorm using jsTestDriver.

actionsTestAllChartsFunctions.test.js only requires a file I created. testDates.test.js and testButtons.test.js both require jQuery and sinon. testButtons also requires D3.

Actual tests and my code do not appear to be the issue. As I've said the tests pass perfectly. There was an error with using 'let' in the past but switching to all 'var' while not ideal, did solve the error.

load:
  - allCharts.js
  - tests/dependencies/sinon732.js
test:
  - tests/Functional/javascriptTests/actionsTestAllChartsFunctions.test.js

timeout: 60 

is enough to break code coverage.

I expected to get code coverage for all files (initially my testDriver was supposed to be running all tests together until I split it to root out the issue) but anything that requires sinon can no longer get code coverage. Not using sinon is impossible unless there is some other library that can stub, mock and spy on functions.


Solution

  • In the sinon file (works for every version I've tested) go to var TYPE_MAP = {

    Once there:

    • change function: to 'function':
    • change number: to 'number':
    • change object: to 'object':
    • change regexp: to 'regexp':
    • change string: to 'string':

    This fixes this issue.