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

[no ticket][risk=no] Puppeteer test log improvement #4660

Merged
merged 17 commits into from
Mar 10, 2021

Conversation

aweng98
Copy link
Contributor

@aweng98 aweng98 commented Mar 7, 2021

Adding log timestamp and saving single test log file.

New test logs structure:

Screen Shot 2021-03-09 at 9 51 34 AM

@aweng98 aweng98 changed the title Aw/e2e jest reporter [no ticket][risk=no] Puppeteer test log improvement Mar 8, 2021
Comment on lines -40 to -42
await savePageToFile(this.page);
await takeScreenshot(this.page);
throw (err);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

redundant. saving screenshot and html is done in
handleTestEvent

@@ -3,7 +3,6 @@ const { TEST_MODE } = process.env;

module.exports = {
"verbose": false,
"bail": 1, // Stop running tests after `n` failures
Copy link
Contributor Author

Choose a reason for hiding this comment

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

setting bail prevents test log write to file. Alternative is implemented in PuppeteerCustomEnvironment's handleTestEvent.

Comment on lines 60 to 65
if (this.failedTest && event.name === 'test_start') {
event.test.mode = 'skip';
}
if (super.handleTestEvent) {
super.handleTestEvent(event, state)
}
Copy link
Contributor Author

@aweng98 aweng98 Mar 8, 2021

Choose a reason for hiding this comment

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

Alternative to Jest bail.
#6527 comment

@@ -74,6 +69,7 @@
"tslint-config-prettier": "1.18.0",
"tslint-eslint-rules": "5.4.0",
"tslint-microsoft-contrib": "6.2.0",
"typescript": "4.1.2"
"typescript": "4.1.2",
"winston": "^3.3.3"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

winston: timestamp and saving to file.

@@ -7,8 +7,8 @@
"license": "BSD",
"scripts": {
"impersonate-test-user": "env-cmd -x ../api/project.rb generate-impersonated-user-token --impersonated-user=\\$USER_NAME --output-token-filename=../e2e/puppeteer-access-token.txt",
"_test": "yarn impersonate-test-user && jest",
"_test:debugTest": "yarn impersonate-test-user && node --inspect-brk node_modules/.bin/jest",
"_test": "yarn impersonate-test-user && jest --no-color",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

ansi code makes test log harder to read.

@aweng98 aweng98 requested a review from calbach March 8, 2021 18:15
Copy link
Contributor

@calbach calbach left a comment

Choose a reason for hiding this comment

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

Looking good, thanks - a couple of questions on this

@@ -82,6 +85,7 @@ beforeEach(async () => {
'/cdrVersions',
'/config',
'/user-recent-workspaces',
'/user-recent-resources',
Copy link
Contributor

Choose a reason for hiding this comment

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

First time seeing this list. This should have a comment about why you would add something to this list.

Also, page-visits does not have a /, this seems like a bug

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

console.info(`Running ${path.parse(test.path).name} at ${time}`);
}

// @ts-ignore
Copy link
Contributor

Choose a reason for hiding this comment

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

Why? Aren't you in a JS file anyway?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

tslint is checking all files (.ts, .js) because tsconfig.json is config with "inclue": ["/*"]. tslint is soon to be replaced by eslint. We can safely ignore this "bug" at this time.

});

// Save test results to a file.
if (!fs.existsSync(this.logDir)) fs.mkdirSync(this.logDir);
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: generally we avoid 1 line if statements like this in the codebase, or without brackets

Copy link
Contributor Author

Choose a reason for hiding this comment

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

corrected.


constructor(globalConfig, options) {
if (globalConfig.verbose === true) {
throw Error("Verbose must be false or Console messages won't be available.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this just be an console error? Is there no situation where you'd want to run like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In "verbose": true mode, console logs are not saved by jest internally, so logs won't be available to onTestResult function. I want to stop the test if it was changed. IMO, there isn't any good reason to use verbose: true.

// Get test name.
const today = new Date();
const testName = path.parse(testResult.testFilePath).name;
const testLog = `${this.logDir}/${testName}-${today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate()}.log`;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is the date included here? This seems like an odd granularity to choose. If you're trying to use this to get a unique filename, you'll probably need to be more specific (e.g. minute-level). If you want to overwrite previous files, then you may as well just exclude the date entirely.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right. I want overwrite. Removed time string.

break;
default:
break;
}

if (this.failedTest && event.name === 'test_start') {
event.test.mode = 'skip';
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't understand what is happening here, please add comments

Copy link
Contributor Author

Choose a reason for hiding this comment

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

jest-circus is used as jest runner. It hooks into test event and state data.
It's fail fast. Because I can't use bail option with a custom logger, I have to find another way to stop other tests from running after first failure. If first failure has happened, all following unexecuted tests will be marked as skip.
Comments also added to file.

format: format.combine(
format.prettyPrint(),
format.splat(),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice

options: { flags: 'w' },
handleExceptions: true,
});
fileLogger.clear().add(transports);
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain the decision to use a single logger and then replace the output file - instead of creating a separate logger for each test case? Could you not just create a new one right here rather than mutating shared global state?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, I'm creating a new instance of winston logger here. Creating a separate log file for each test case. I didn't want to include fileLogger here is because it might be reusable for other purpose in future.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

On second thought: I think I know what you meant. It's a good idea.
Moving fileLogger code to here. creating a new log file for every test.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I realized I asked for this, but am I understanding correctly that now the network log / console logs will not be in the individual test case log files? If so - would probably just revert to the previous approach if you can't use individual loggers there.

It will be very useful to have a clear separation of network logs across test cases - right now it's hard to tell since you have to scan the logs to know how far back you can look for the problematic test case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Test network and console logs will be saved in individual test log file. they're not lost. It should be easier to read the test log when a failure has happened.

Copy link
Contributor

Choose a reason for hiding this comment

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

True, I do seem them in the Circle run. I'm confused as to how they are getting there though, since this initial jest setup seems to reference the global logger: https://github.com/all-of-us/workbench/pull/4660/files#diff-9771f32e200b100d3bf9acedfc38dae6209ad815c5e214a31719188ddd392f1dR128

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see. That logger object is a separate winston logger that only logs to console. It doesn't have a file transport.
However, console logs are automatically saved by jest and later they can be retrieved in onTestResult function when verbose: false.

return jsHandle.executionContext().evaluate(obj => {
if (obj instanceof Error)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use brackets, also please add a comment - I don't follow this

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@aweng98 aweng98 marked this pull request as ready for review March 9, 2021 15:09
@aweng98 aweng98 force-pushed the aw/e2e-jest-reporter branch from d2d8d0b to 12f9dc0 Compare March 9, 2021 18:16
} catch (err) {
console.error(`❗ ${title}\nException occurred when getting error.\n${err}`);
console.error(`❗ "${title}"\nException occurred when getting page error.\n${err}`);
}
});

page.on('pageerror', async (error) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

FYI: Somehow logging of console pageerror and error are not working. I don't have a solution at this time.

console.error
      PAGEERROR: "Edit Workspace | [Test] All of Us Researcher Workbench"
      Error: Object
      Object

      219 |     const title = await getPageTitle();
      220 |     try {
    > 221 |       console.error(`PAGEERROR: "${title}"\n${error.toString()}\n${error.message}\n${error.stack}`);
          |               ^
      222 |       console.log('');
      223 |     } catch (err) {
      224 |       console.error(`❗ "${title}"\nPage exception occurred when getting pageerror.\n${err}`);

      at jest.test-setup.ts:221:15

Copy link
Contributor

@calbach calbach left a comment

Choose a reason for hiding this comment

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

One follow-up comment inline: please address before merging.

Also, from looking at the CircleCI page, I'm noticing it's actually pretty hard to know which logfile I should open to get more details, since I have to dig into the logs to figure out the test suite name, and map that to which one failed. Have you considered ways of addressing this? For example - if a test suite fails, maybe move these into separate pass/fail directories, or rename them to "FAILED", or possibly just remove the logfiles for passing suites?

Also - thoughts on splitting by individual test case, rather than test suite? I think test suite is probably OK for now, but something we may want to consider if this becomes problematic for debugging

options: { flags: 'w' },
handleExceptions: true,
});
fileLogger.clear().add(transports);
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I realized I asked for this, but am I understanding correctly that now the network log / console logs will not be in the individual test case log files? If so - would probably just revert to the previous approach if you can't use individual loggers there.

It will be very useful to have a clear separation of network logs across test cases - right now it's hard to tell since you have to scan the logs to know how far back you can look for the problematic test case.

Comment on lines 25 to 31
let testLogName;
testResult.testResults.forEach((result) => {
const status = result.status;
if (status === 'failed') {
testLogName = `${this.logDir}/${testName}-FAILED.log`;
} else {
testLogName = `${this.logDir}/${testName}.log`;
}
});
Copy link
Contributor Author

Choose a reason for hiding this comment

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

More verbose code but it does the job to find failed test log a little easier. FAILED string is added to log file name.

@aweng98 aweng98 force-pushed the aw/e2e-jest-reporter branch from 7a255a3 to d5ae159 Compare March 10, 2021 00:00
@aweng98 aweng98 merged commit ac0cd0a into master Mar 10, 2021
@aweng98 aweng98 deleted the aw/e2e-jest-reporter branch March 10, 2021 00:27
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.

2 participants