Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(angular): update Karma config path in Angular preset #2548

Conversation

LayZeeDK
Copy link
Contributor

@LayZeeDK LayZeeDK commented Oct 10, 2020

  • Update Karma config path in Angular preset to reflect default path in Angular CLI 9+ projects.
  • Update Angular project in e2e using npx -p @angular/cli@9.0.7 ng new (...) to use default configurations and paths. Downgrading from Angular 9.1 to Angular 9.0 to make sure we support this version.
  • Update Angular CLI project in perf using npx -p @angular/cli@9.0.7 ng new (...) to use default configurations and paths. Downgrading from Angular 9.1 to Angular 9.0 to make sure we support this version.
  • Use Angular 9 Strict mode configurations, except for strictTemplate: true for now.
  • Lock mutation report assertions in e2e/test/angular-project/verify/verify.ts because of Stryker configuration changes:
    • Disabled TypeScript Checker as it has issues with TypeScript <4.0 and Angular in this monorepo without changing default Angular CLI TypeScript configurations.
    • Enabled perTest coverage analysis since it's supported for Karma in Stryker 4.

@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 10, 2020

Trying to figure out why tests are failing in the e2e pipeline.

It sounds like ngcc (Angular Compatibility Compiler) issues, but that makes me wonder how this could have worked before. Maybe something changed in Angular 9.1. One option is to use the postinstall hook to run ngcc. Come to think of it, there were a lot of issues due to ngcc in early Angular 9 versions.

Possible changes affecting this:

  1. core-js removed.
  2. emitDecoratorMetadata option removed from tsconfig.json.
  3. A combination of (1) and (2).
  4. coverageAnalysis set to "perTest" in stryker.conf.json in e2e.
  5. Downgraded e2e project from Angular 9.1.x to 9.0.7.

This is the error reported:

21:13:16 (4086) ERROR DryRunExecutor One or more tests failed in the initial test run:
	AppComponent should create the app
		Error: Unexpected value 'BrowserDynamicTestingModule' imported by the module 'DynamicTestModule'. Please add an @NgModule annotation.
    at verifySemanticsOfNgModuleDef (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:38946:1)
    at http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:38964:1
    at <Jasmine>
    at verifySemanticsOfNgModuleDef (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:38958:1)
    at Function.get (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:38910:1)
    at R3TestBedCompiler.applyProviderOverridesToModule (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/testing/fesm2015/testing.js:2086:44)
    at R3TestBedCompiler.compileTestModule (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/testing/fesm2015/testing.js:2385:1)
    at R3TestBedCompiler.finalize (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/testing/fesm2015/testing.js:1879:1)
    at TestBedRender3.get testModuleRef [as testModuleRef] (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/testing/fesm2015/testing.js:3252:1)
    at TestBedRender3.inject (http:// localhost:9876/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@angular/core/testing/fesm2015/testing.js:3109:1)

Solution

Adding ngcc to the postinstall hook did the trick, so (5) was the cause of this issue.

@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 10, 2020

One last thing left to do: Decide whether the test in e2e/test/angular-project/verify/verify.ts needs to be updated.

This is the test:

import { expectMetrics } from '../../../helpers';

describe('After running stryker on angular project', () => {
  it('should report 20% or 7% mutation score', async () => {
    await expectMetrics({
      mutationScore: 33.33,
      killed: 2,
      survived: 4,
      noCoverage: 0,
      compileErrors: 1,
    })
    //  -------------------|---------|----------|-----------|------------|----------|---------|
    //  File               | % score | # killed | # timeout | # survived | # no cov | # error |
    //  -------------------|---------|----------|-----------|------------|----------|---------|
    //  All files          |   20.00 |        1 |         0 |          4 |        0 |       0 |
  });
});

Test result:

  1) After running stryker on angular project
       should report 20% or 7% mutation score:

      AssertionError: expected { Object (mutationScore, killed, ...) } to deeply equal { Object (mutationScore, killed, ...) }
      + expected - actual

       {
      -  "compileErrors": 0
      -  "killed": 3
      -  "mutationScore": 42.86
      -  "noCoverage": 4
      -  "survived": 0
      +  "compileErrors": 1
      +  "killed": 2
      +  "mutationScore": 33.33
      +  "noCoverage": 0
      +  "survived": 4
       }

The test description isn't reflecting the current assertions either. Please advice.

@LayZeeDK LayZeeDK force-pushed the LayZeeDK/feat/update-karma-config-path-in-Angular-preset branch from c0c85d2 to 074a357 Compare October 10, 2020 21:45
@bartekleon
Copy link
Member

For me it looks good, tho - it seems we don't support angular 9.1>=? Do you have any idea if / when we can support it with the same setup like this one

@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 11, 2020

For me it looks good, tho - it seems we don't support angular 9.1>=? Do you have any idea if / when we can support it with the same setup like this one

I also confirmed that Stryker 4 works for Angular versions 9.1 and 10.1. This is described in PR#41 for the Stryker Handbook and in the Stryker 4 announcement.

I usually target the lowest supported version to make sure that there are no regressions. Maybe we could add another project and try to keep it updated to the most recent version of Angular (version 11.0's release date is November 11th 2020).

@LayZeeDK LayZeeDK force-pushed the LayZeeDK/feat/update-karma-config-path-in-Angular-preset branch from 7c5ef2a to 59052c5 Compare October 11, 2020 13:14
@nicojs
Copy link
Member

nicojs commented Oct 12, 2020

I usually target the lowest supported version to make sure that there are no regressions. Maybe we could add another project and try to keep it updated to the most recent version of Angular (version 11.0's release date is November 11th 2020).

Yes, that is what we should do. I started doing this for mocha (we're supporting mocha@5 at the low end).

It will make the e2e tests even slower (Angular needs a lot of dependencies), but there is no easy way around that without compromising the test.

About the failing e2e test, I think it is a valid change since you removed the @stryker-mutator/typescript-checker plugin (no more compile errors) and added coverageAnalayis: "perTest" (so some survived are now noCoverage).

Could we maybe add the same tests for angular@^10, but with the @stryker-mutator/typescript-checker plugin? I would be happy to do this after we merge this in if you don't have the time @LayZeeDK.

I'll have a proper look this week.

@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 12, 2020

About the failing e2e test, I think it is a valid change since you removed the @stryker-mutator/typescript-checker plugin (no more compile errors) and added coverageAnalayis: "perTest" (so some survived are now noCoverage).

I misread the 4.0 announcement post; @stryker-mutator/typescript was removed, not @stryker-mutator/typescript-checker. I added it back to the configuration of this project.

I added the "perTest" setting because it seems that it wasn't supported with Stryker 3, but now is supported with Stryker 4.

@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 12, 2020

After I added back the TypeScript Checker, this error is reported:

    19:38:51 (3931) ERROR Stryker Error: Error: An error occurred during initialization of the "typescript" checker. Inner error: Error: TypeScript error(s) found in dry run compilation: ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,36): error TS1005: ',' expected.\n
    ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,57): error TS1005: ',' expected.

    Error: TypeScript error(s) found in dry run compilation: ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,36): error TS1005: ',' expected.
    ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,57): error TS1005: ',' expected.

        at TypescriptChecker.init (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/typescript-checker/src/typescript-checker.ts:118:13)
        at processTicksAndRejections (internal/process/task_queues.js:97:5)
        at CheckerWorker.init (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/core/src/checker/checker-worker.js:21:21
        at ChildProcessProxyWorker.handleCall (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/core/src/child-proxy/child-process-proxy-worker.js:62:28)
    Error: An error occurred during initialization of the "typescript" checker. Inner error: Error: TypeScript error(s) found in dry run compilation: ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,36): error TS1005: ',' expected.
    ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,57): error TS1005: ',' expected.

    Error: TypeScript error(s) found in dry run compilation: ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,36): error TS1005: ',' expected.
    ../../node_modules/@stryker-mutator/api/src/core/range.d.ts(4,57): error TS1005: ',' expected.

        at TypescriptChecker.init (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/typescript-checker/src/typescript-checker.ts:118:13)
        at processTicksAndRejections (internal/process/task_queues.js:97:5)
        at CheckerWorker.init (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/core/src/checker/checker-worker.js:21:21)
        at ChildProcessProxyWorker.handleCall (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/core/src/child-proxy/child-process-proxy-worker.js:62:28)
        at CheckerWorker.init (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/core/src/checker/checker-worker.js:24:27)
        at processTicksAndRejections (internal/process/task_queues.js:97:5)
        at ChildProcess.<anonymous> (/home/runner/work/stryker/stryker/e2e/test/angular-project/node_modules/@stryker-mutator/core/src/child-proxy/child-process-proxy.js:132:68)
        at ChildProcess.emit (events.js:315:20)
        at emit (internal/child_process.js:876:12)
        at processTicksAndRejections (internal/process/task_queues.js:85:21)

Remember that this project uses TypeScript version 3.7.5.

As seen in this TypeScript playground, range.ts is incompatible with TypeScript 3.7.

Labeled tuple elements were added in TypeScript 4.0, so range.ts is currently incompatible with e2e project using TypeScript <4.0.

// range.ts
/**
 * Represents a location in a file by range.
 */
type Range = [fromInclusive: number, toExclusive: number];

export default Range;

This is the declarations output in range.d.ts in @stryker-mutator/core v4.0.0:

// range.d.ts
/**
 * Represents a location in a file by range.
 */
declare type Range = [fromInclusive: number, toExclusive: number];
export default Range;
//# sourceMappingURL=Range.d.ts.map

Meaning TypeScript <4.0 is not supported for a bunch of the APIs.

TypeScript 4.0 is supported by Angular 10.1.

Copy link
Member

@nicojs nicojs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for picking this up @LayZeeDK.

I personally don't think the performance test should have to be downgraded to 9.0. We should be performance testing Stryker itself, not Angular. Performance should change that much between angular releases (other than Angular specifics). Do you agree?

@@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The performance test doesn't have to be in this PR I think. We don't need that to be on the lower end of our Angular supported versions.

Copy link
Contributor Author

@LayZeeDK LayZeeDK Oct 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would still want it to follow current Angular CLI project structure, especially configurations such as karma.conf.js. I will upgrade it to Angular latest.

@nicojs
Copy link
Member

nicojs commented Oct 13, 2020

After I added back the TypeScript Checker, this error is reported:

@LayZeeDK wow! That is very strange. Why would the typescript compiler pick up the types of the TypeScript checker itself? I've opened #2550 for it. This shouldn't happen, great find!

@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 13, 2020

Unless you have something up your sleeve for fixing this bug right away, I will remove the TypeScript checker from the Angular 9.0 e2e project.

Then I will add an Angular latest e2e project which will include the TypeScript checker. Finally, I will lock mutation report assertions so that we can get to merging this PR.

@LayZeeDK
Copy link
Contributor Author

After I added back the TypeScript Checker, this error is reported:

@LayZeeDK wow! That is very strange. Why would the typescript compiler pick up the types of the TypeScript checker itself? I've opened #2550 for it. This shouldn't happen, great find!

Let me verify that this is a problem for Angular 9 projects outside of this monoreppo, using the NPM package directly.

@nicojs
Copy link
Member

nicojs commented Oct 13, 2020

I figured out what the issue was. By default, @stryker-mutator/typescript-checker will use your tsconfig.json file, instead of tsconfig.app.json. It will add verify/verify.ts to the TS build, which includes assertions that import the @stryker-mutator/api/src/core/range.d.ts file (in a roundabout way), hence the compile error.

Configuring "tsconfigFile": "tsconfig.app.json" solved this issue. I'm closing issue #2550

However, the next issue arrises:

21:54:05 (10637) INFO DryRunExecutor Initial test run succeeded. Ran 3 tests in 2 seconds (net 203 ms, overhead 2048 ms).
21:54:05 (10637) ERROR Stryker Error: Error: Tried to check file "/home/nicojs/github/stryker/e2e/test/angular-project/src/app/app.component.ts" (which is part of your typescript project), but no watcher is registered for it. Changes would go unnoticed. This probably means that you need to expand the files that are included in your project.

I actually know the issue here, since I did some investigation on this when migrating the angular project. The problem is that the tsconfig.app.json doesn't properly define which files are included in the project (for some reason). TypeScript will never be able to compile this normally, but since the angular team uses it's own compiler (Ivy?), it works for them.

Changing this:

{
  "files": [
    "src/main.ts",
    "src/polyfills.ts"
  ],
  "include": [
    "src/**/*.d.ts"
  ]
}

To this:

{
  "include": [
    "src/main.ts",
    "src/polyfills.ts",
    "src/app/**/*",
    "src/**/*.d.ts"
  ],
  "exclude": [
    "src/app/**/*.spec.ts"
  ]
}

Works:

> stryker run

22:08:48 (11702) INFO ConfigReader Using stryker.conf.json
22:08:48 (11702) INFO InputFileResolver Found 4 of 27 file(s) to be mutated.
22:08:48 (11702) INFO Instrumenter Instrumented 4 source file(s) with 7 mutant(s)
22:08:48 (11702) INFO ConcurrencyTokenProvider Creating 1 checker process(es) and 1 test runner process(es).
22:09:05 (11702) INFO DryRunExecutor Starting initial test run. This may take a while.
22:09:07 (11702) INFO DryRunExecutor Initial test run succeeded. Ran 3 tests in 2 seconds (net 194 ms, overhead 1947 ms).
Mutation testing  [==================================================] 100% (elapsed: <1m, remaining: n/a) 3/3 tested (0 survived, 0 timed out)

#3. [NoCoverage] ConditionalExpression
/home/nicojs/github/stryker/e2e/test/angular-project/src/main.ts:6:4
-   if (environment.production) {
+   if (true) {

#4. [NoCoverage] ConditionalExpression
/home/nicojs/github/stryker/e2e/test/angular-project/src/main.ts:6:4
-   if (environment.production) {
+   if (false) {

#5. [NoCoverage] BlockStatement
/home/nicojs/github/stryker/e2e/test/angular-project/src/main.ts:6:28
-   if (environment.production) {
-     enableProdMode();
-   }
+   if (environment.production) {}

#6. [NoCoverage] ArrowFunction
/home/nicojs/github/stryker/e2e/test/angular-project/src/main.ts:11:9
-     .catch(err => console.error(err));
+     .catch(() => undefined);

Ran 0.57 tests per mutant on average.
-------------------|---------|----------|-----------|------------|----------|---------|
File               | % score | # killed | # timeout | # survived | # no cov | # error |
-------------------|---------|----------|-----------|------------|----------|---------|
All files          |   33.33 |        2 |         0 |          0 |        4 |       1 |
 app               |  100.00 |        2 |         0 |          0 |        0 |       1 |
  app.component.ts |  100.00 |        2 |         0 |          0 |        0 |       1 |
 main.ts           |    0.00 |        0 |         0 |          0 |        4 |       0 |
-------------------|---------|----------|-----------|------------|----------|---------|
22:09:14 (11702) INFO HtmlReporter Your report can be found at: file:///home/nicojs/github/stryker/e2e/test/angular-project/reports/mutation/html/index.html
22:09:14 (11702) INFO MutationTestExecutor Done in 26 seconds.

I think we should do the following here:

  1. Also add a test for angular 10 (or 11) in a separate PR.
  2. Not include the typescript-checker here, but add it in the Angular@current e2e test
  3. Merge the perf test now in, but upgrade it to Angular@current

Do you agree @LayZeeDK and @kmdrGroch ?

@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 13, 2020

Where is this option added?

"tsconfigFile": "tsconfig.app.json"

It's an option for the TypeScript Checker in stryker.conf.json, right?

@LayZeeDK
Copy link
Contributor Author

As noted in #2550, the TypeScript Checker works outside of this monorepo with Angular CLI's out-of-the-box configurations, even with Angular 9.0 and TypeScript 3.7 👍

@LayZeeDK
Copy link
Contributor Author

Regarding files and include/exclude options, the Angular team introduced solution-style TypeScript configurations in Angular CLI 10.0 to address this, but rolled them back in Angular CLI 10.1 because of a bunch of performance issues, tooling issues and whatnot.

@LayZeeDK LayZeeDK force-pushed the LayZeeDK/feat/update-karma-config-path-in-Angular-preset branch from 9b299f0 to 59052c5 Compare October 13, 2020 20:26
@LayZeeDK
Copy link
Contributor Author

LayZeeDK commented Oct 13, 2020

I think we should do the following here:

  1. Also add a test for angular 10 (or 11) in a separate PR.
  2. Not include the typescript-checker here, but add it in the Angular@current e2e test
  3. Merge the perf test now in, but upgrade it to Angular@current

Do you agree @LayZeeDK and @kmdrGroch ?

I agree. I removed TypeScript checker from e2e/test/angular-project, so this PR should be good to go as soon as we lock the mutation report assertions.

For (1) and (3), I would like to use Angular 10 Strict mode (ng new project-name --strict) in both perf/test/angular-cli and e2e/test/angular-latest. It might require us to make some changes in perf/test/angular-cli.

@LayZeeDK
Copy link
Contributor Author

Looks like we're ready to merge 👍

@nicojs nicojs merged commit 986acba into stryker-mutator:master Oct 14, 2020
@LayZeeDK LayZeeDK deleted the LayZeeDK/feat/update-karma-config-path-in-Angular-preset branch October 14, 2020 14:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants