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

Record and Playback - refactoring #4281

Merged
merged 96 commits into from
Aug 23, 2019

Conversation

HarshaNalluru
Copy link
Member

@HarshaNalluru HarshaNalluru commented Jul 11, 2019

Currently, the base recorder which allows recording the tests and playing them back is being duplicated across packages(for both node and browser that I and Caio have worked on).

Example - recorder.ts for storage-queue package

In an effort to avoid the duplication of the recorder, this PR attempts to unify the recorder modules and provide a common utils library in the repo.

So, this new package "@azure/test-utils-recorder" can be added as a devDependency in an sdk (for example, storage-queue) to leverage the functionalities provided by the "recorder" to record the tests and generate recordings and to playback those recordings.

@HarshaNalluru HarshaNalluru added the Client This issue points to a problem in the data-plane of the library. label Jul 11, 2019
@HarshaNalluru HarshaNalluru requested a review from kinelski July 11, 2019 23:24
@HarshaNalluru HarshaNalluru self-assigned this Jul 11, 2019
@HarshaNalluru HarshaNalluru requested a review from sadasant July 11, 2019 23:40
const skip = [
// Abort
"browsers/aborter/recording_should_abort_after_aborter_timeout.json"
];
Copy link
Member Author

@HarshaNalluru HarshaNalluru Jul 11, 2019

Choose a reason for hiding this comment

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

The eventual plan is to remove the skip list - #4084 (comment)
Will work out in a future PR.

Copy link
Member Author

Choose a reason for hiding this comment

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

if (isPlayingBack) {
// Providing dummy values to avoid the error
env.ACCOUNT_NAME = "fakestorageaccount";
env.ACCOUNT_KEY = "aaaaa";
Copy link
Member Author

Choose a reason for hiding this comment

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

More work on ENV variables
#4284

new RegExp(env.ACCOUNT_NAME, "g"),
"fakestorageaccount"
);
if (env.ACCOUNT_KEY) {
Copy link
Member Author

Choose a reason for hiding this comment

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

More work on ENV variables
#4284

// Nise module does not have a native implementation of record/playback like Nock does
// This class overrides requests' 'open', 'send' and 'onreadystatechange' functions, adding our own code to them to deal with requests
export class NiseRecorder extends BaseRecorder {
private readonly sasQueryParameters = ["se", "sig", "sp", "spr", "srt", "ss", "st", "sv"];
Copy link
Member Author

@HarshaNalluru HarshaNalluru Aug 14, 2019

Choose a reason for hiding this comment

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

This is to filter sasQueryParameters in the browser tests for storage sdks.
Code related to this doesn't affect if such query params are not present.
(Meaning.. for example, this doesn't affect keyvault sdks - #4749 (comment))

Will work in a future PR to update this make the recorder more generic.

/cc - @sadasant

Copy link
Contributor

Choose a reason for hiding this comment

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

These hardcoded parameters should be passed into the library rather than part of the library itself. Different services may have their own query parameters, potentially.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree.

Copy link
Member Author

Choose a reason for hiding this comment

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

Addressed below - #4281 (comment)

@HarshaNalluru HarshaNalluru changed the title [WIP] Record and Playback - refactoring Record and Playback - refactoring Aug 14, 2019
For example

```typescript
describe("Aborter", () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I thought we weren't using this name

Copy link
Member Author

@HarshaNalluru HarshaNalluru Aug 21, 2019

Choose a reason for hiding this comment

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

Hmm. We haven't updated the title in storage test-suites.

Updated this to "Some Random Test Suite" here.


- The above methods can be called from the `before` section so that the tests can leverage the environment variables.

- Currently, the environment variables for storage-packages are managed by the recorder. `ACCOUNT_NAME` is replaced with `"fakestorageaccount"`, secret part of `ACCOUNT_SAS` and `ACCOUNT_KEY` are replaced with `"aaaaa"`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Storage-specific stuff should live outside of the recorder package.

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed

env.ACCOUNT_KEY = "aaaaa";
env.ACCOUNT_SAS = "aaaaa";
env.STORAGE_CONNECTION_STRING = `DefaultEndpointsProtocol=https;AccountName=${
env.ACCOUNT_NAME
Copy link
Contributor

Choose a reason for hiding this comment

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

Storage-specific functionality should be outside of the recorder. I see the TODO, but it'd be good to make sure we're landing something general first, and then we can land PRs for storage and kv to use it.

Copy link
Member Author

@HarshaNalluru HarshaNalluru Aug 22, 2019

Choose a reason for hiding this comment

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

Removed

"/recording_" +
this.formatPath(testTitle) +
"." +
ext;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we test for node?

// Nise module does not have a native implementation of record/playback like Nock does
// This class overrides requests' 'open', 'send' and 'onreadystatechange' functions, adding our own code to them to deal with requests
export class NiseRecorder extends BaseRecorder {
private readonly sasQueryParameters = ["se", "sig", "sp", "spr", "srt", "ss", "st", "sv"];
Copy link
Contributor

Choose a reason for hiding this comment

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

These hardcoded parameters should be passed into the library rather than part of the library itself. Different services may have their own query parameters, potentially.

responseHeaders[key] = value;
}

// We're not storing SAS Query Parameters because they may contain sensitive information
Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like the service should send you the additional set of parameters that may contain sensitive information

Copy link
Member Author

@HarshaNalluru HarshaNalluru Aug 22, 2019

Choose a reason for hiding this comment

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

Updated by exporting a new method called skipQueryParams, where the params can be provided by the sdk itself, for example, SAS query params can be provided by storage-queue package.

const reqStateChange = req.onreadystatechange;
req.onreadystatechange = function() {
// Record the request once the response is obtained
if (req.readyState === 4) {
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 say more about what readyState is, and what in particular 4 is? Could this be an enum instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added some comments stating what readyState refers to.

Copy link
Contributor

Choose a reason for hiding this comment

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

I mean more the hard-coded 4. Why is it 4 and not 3 or 5?

Copy link
Member Author

@HarshaNalluru HarshaNalluru Aug 22, 2019

Choose a reason for hiding this comment

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

More info - https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/readyState


image

89a9188 - Added the following comment
readyState = 4 refers to the completion of the operation.

Should I talk more about it?

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah okay, so there isn't an official enumeration, just the number. It's fine to leave it as is, but you may want to link to the documentation for people who try to read the code later

* @export
* An interface that allows recording and playback capabilities for the tests in Azure TS SDKs.
*/
export interface Recorder {
Copy link
Contributor

Choose a reason for hiding this comment

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

If only one Recorder type is exposed, I think it's fine to keep the name.

@HarshaNalluru HarshaNalluru requested a review from sophiajt August 22, 2019 19:30
@HarshaNalluru
Copy link
Member Author

HarshaNalluru commented Aug 22, 2019

@jonathandturner and @sadasant

Tested the new @azure/test-utils-recorder with keyvault-secrets package

Findings/comments/questions/suggestions

  • unit-test:browser is "echo skipped" - Is there a reason behind skipping the unit tests for the browser ?
  • Deleted the recordings
  • Generated the recordings for node tests - Successful
  • Playback is also successful for node tests - Successful
  • Some of the tests have same title and are in the same test-suite - this needs to be updated
  • I've observed that we need to set env variables in the .env file and using set var=value
    We can update the code to import env variables from .env file using dotenv all the time and reduce the complexity of doing set var=value each time we run the tests.
  • One suggestion to update the test:node command to
    "test:node": "npm run clean && npm run build:test && npm run integration-test:node", and use it instead of having to run both build:test and integration:test
    [ I kept forgetting that I need to run build:test before running integration-test:node"]
  • Browser tests
    • With @azure/test-utils-recorder, tests executed successfully in "record" mode - generated recordings as well.
    • In the playback mode, two tests succeeded and then exited. Reason being the usage of abort in the test. It is a known issue and we skip the test in browsers during playback mode.
    • Conclusion - Record and playback are successful for the browser tests

/cc - @ramya-rao-a

"integration-test:node": "echo skipped",
"integration-test": "npm run integration-test:node && npm run integration-test:browser",
"lint:fix": "eslint \"src/**/*.ts\" \"test/**/*.ts\" -c ../../.eslintrc.json --fix --fix-type [problem,suggestion]",
"lint": "eslint -c ../../.eslintrc.json src test --ext .ts -f node_modules/eslint-detailed-reporter/lib/detailed.js -o template-lintReport.html || exit 0",
Copy link
Member

Choose a reason for hiding this comment

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

Can you submit another PR and change the lint step to :
"lint": "eslint -c ../../.eslintrc.json src test --ext .ts -f html -o recorder-lintReport.html || exit 0",

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks

Copy link
Member Author

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Client This issue points to a problem in the data-plane of the library.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants