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

fix(testing): fix tests on windows #131

Closed
wants to merge 9 commits into from
Closed

Conversation

Tlacenka
Copy link
Collaborator

@Tlacenka Tlacenka commented Oct 18, 2023

In this PR, I identified and fixed various issue while running tests in the Windows environment:

  • shell needs to be specified to run programs in command shell on Windows, as described here
  • path notation on Windows is different
  • JSON formatting is different for UNIX and Windows
  • writing into files replaced by echo command which works seamlessly on Windows
  • glob patterns require extra quotation marks for argument expansion on Linux

I also extracted the runner config for writing report into a file to a separate function (there was a lot of duplicate code to keep consistent).

@BioPhoton BioPhoton added the 🔬 testing writing tests label Oct 20, 2023
@Tlacenka Tlacenka changed the title Fix tests on windows fix(testing): fix tests on windows Oct 23, 2023
@matejchalk matejchalk mentioned this pull request Oct 24, 2023
1 task
@Tlacenka Tlacenka force-pushed the fix-tests-on-windows branch 2 times, most recently from 941f27d to c6155df Compare October 24, 2023 09:51
@Tlacenka Tlacenka added this to the 1. Internal MVP milestone Oct 24, 2023
@Tlacenka Tlacenka self-assigned this Oct 24, 2023
Copy link
Collaborator

@matejchalk matejchalk left a comment

Choose a reason for hiding this comment

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

Really great to have this fixed finally, so that the codebase is now usable on Windows 😅

As discussed, I created a follow-up for automatically checking it: #141

Comment on lines +24 to +36
const osAuditOutput =
platform() === 'win32'
? JSON.stringify(audits)
: "'" + JSON.stringify(audits) + "'";

const filePath = join(process.cwd(), 'tmp/report.json');
const unixFilePath = toUnixPath(filePath);

expect(createFileWriteRunnerConfig(audits, filePath)).toStrictEqual({
command: 'echo',
args: [osAuditOutput, '>', unixFilePath],
outputFile: unixFilePath,
});
Copy link
Collaborator

Choose a reason for hiding this comment

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

The test code is basically the same as the function it's testing. If we're gonna test this (not sure it makes sense to test a testing utility 🤔), I would have different test cases per OS (mock os.platform() value).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If I did that, I would then be testing the unix path function which already has separate tests. Removed.

Comment on lines +15 to +16
args: [auditOutput, '>', toUnixPath(outputFilePath)],
outputFile: toUnixPath(outputFilePath),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should these be UNIX paths on Windows? 🤨

Copy link
Collaborator

Choose a reason for hiding this comment

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

maybe path.join or path.normalize could be used instead

Copy link
Collaborator

@matejchalk matejchalk Oct 25, 2023

Choose a reason for hiding this comment

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

I think just outputFile: outputFilePath should be fine, the file path should be platform-dependant.

The toUnixPath function is needed by the ESLint plugin, because it emits source file issues and needs to convert them from absolute platform-dependant paths to relative Git paths. I'm not aware of any other use case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

If you say so. I wanted to make sure that the resulting path would be safe but if that is the responsibility of the caller, sure.

@@ -7,6 +7,7 @@
"dependencies": {
"@code-pushup/models": "*",
"@code-pushup/core": "*",
"@code-pushup/utils": "*",
Copy link
Collaborator

Choose a reason for hiding this comment

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

As far as I can tell, @code-pushup/utils is imported only in test files and packages/cli/code-pushup.config.ts. So I don't think this dependency should be here. The lint rule takes only imports in "production" files into account, which are configured here in nx.json.

I believe we're just missing a glob which will exclude the config files (since we're only using those for testing) - probably something like ['**/*/code-pushup.config.*.ts', '**/*/code-pushup.config.*.js', '**/*/code-pushup.config.*.mjs'].

Alternatively, we can rename this file to code-pushup.config.mock.ts and then it should be excluded without changing the configuration. Maybe that's better, because it's explicitly marked as testing-only 🤔

Copy link
Collaborator

@BioPhoton BioPhoton left a comment

Choose a reason for hiding this comment

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

Nice improvement of testing! Left some comments.

'--verbose',
'--persist.format=stdout',
],
args: [cliPath, 'collect', '--verbose', '--persist.format=stdout'],
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This test was written by @matejchalk, I merely extracted one of the arguments to a variable. What do you think about this suggestion?

From my point of view, having arguments as an explicit array increases the test readability which is what you want in test code.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I also don't see the point of objectToCliArgs, to be honest. This CLI notation is what the user sees, which makes it more fitting for an E2E test, the wrapper function just obfuscates it.

},
],
)}')`,
runner: createFileWriteRunnerConfig(
Copy link
Collaborator

Choose a reason for hiding this comment

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

we have mock functions in models for that situation living in the test/fixture folder

Copy link
Collaborator Author

@Tlacenka Tlacenka Oct 25, 2023

Choose a reason for hiding this comment

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

This is a function that is reusable for multiple tests (currently in cli and lighthouse plugin) and otherwise would need to be duplicated. In one of my new issues, I plan to address this by extracting reusable functions to a separate package instead of duplicating logic in multiple packages.

import { AuditOutputs, PluginConfig } from '@code-pushup/models';
import { createFileWriteRunnerConfig } from '@code-pushup/utils';
Copy link
Collaborator

Choose a reason for hiding this comment

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

Lets move this into models/test/fixtures/runner.config.mock.ts please

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Unfortunately, this function cannot live in the models package as it would cause a circular dependency. Until a separate testing utils package is created, Matthew advised me to add it to utils and account for one separate usage by duplicating the function logic.

@@ -17,6 +17,7 @@
"skipDefaultLibCheck": true,
"baseUrl": ".",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
Copy link
Collaborator

Choose a reason for hiding this comment

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

For what code do we need this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

In order to mock platform for unit tests, I needed to create a spy for the os.platform() which required import directly from os. Unfortunately, this caused a default export TS error and I had to override it with this option.

@Tlacenka
Copy link
Collaborator Author

There were too many conflicts so I created a new branch and PR #165

@Tlacenka Tlacenka closed this Oct 27, 2023
Tlacenka added a commit that referenced this pull request Oct 27, 2023
In this PR, I identified and fixed various issue while running tests in
the Windows environment:

- shell needs to be specified to run programs in command shell on
Windows, as described
[here](https://stackoverflow.com/questions/60386867/node-spawn-child-process-not-working-in-windows)
- path notation on Windows is different
- JSON formatting is different for UNIX and Windows
- writing into files replaced by echo command which works seamlessly on
Windows
- glob patterns require extra quotation marks for argument expansion on
Linux
- recreating tmp folder caused issues for me so I partially fixed it via
adding the recursive option

Note: This is the same scope as #131. Unfortunately, merging changes
from the test refactor did not go well so I started off a clean branch
and re-applied the changes.
@Tlacenka Tlacenka deleted the fix-tests-on-windows branch October 27, 2023 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🔬 testing writing tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants