Skip to content
This repository has been archived by the owner on Oct 3, 2023. It is now read-only.

Add unit/integration testing for @opencensus/web-instrumentation-zone #104

Merged
merged 4 commits into from
Jun 28, 2019

Conversation

crdgonzalezca
Copy link
Contributor

@crdgonzalezca crdgonzalezca commented Jun 27, 2019

  • Add unit testing for OnPageInteraction class.
  • Integration testing on InteractionTracker which creates fake interaction in other to test all kind of supported tasks (e.g. setTimeout, Promise, HTTP requests).

Additionally, there are some changes little changes:

  • Change InteractionTracker as Singleton as there will be only one InteractionTracker instance always.
  • (Fix) Reset currentEventTracingZone when the interaction has finished before it is reset automatically.
  • Register a initial SpanEventListener in the Tracing (for this case the NOOP_EXPORTER) as this is helpful for testing.
  • Stop tracking periodic tasks (setInterval) as they might never stop and interaction wouldn't be stable.


export class InteractionTracker {
// Allows to track several events triggered by the same user interaction in the right Zone.
private currentEventTracingZone?: Zone;
currentEventTracingZone?: Zone;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does this need to be exposed to tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's necessary to test when there are overlapping interactions and check the interactions have different ID. Also, when there are several event clicks corresponding to the same interaction, we want to make sure there is not a new zone for those click events. I am open to receive recommendations on a way to avoid exposing 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.

Update: I stopped exposing this as final decision was to leave this kind of testing of a future refactoring on InteractionTracker

}

/** Increments the count of outstanding tasks for a given interaction id. */
private incrementTaskCount(interactionId: string) {
incrementTaskCount(interactionId: string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the motivation for exposing these methods and verifying that they are called?

My intuition would be to try to measure this implicitly in the test via seeing how long the interaction took

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The motivation is to make sure we actually count the correct amount of tasks involved in the interaction. The duration of interaction is a good test but might give a wrong testing on the amount of tracked tasks for every interaction, as we actually want to check that, for example, macrotasks are handled. I am open to different approach though.

Copy link
Contributor

Choose a reason for hiding this comment

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

Well, I guess to me the fact that it is counting tasks is more of an implementation detail that is not exposed to the end user of the tracker. So for an integration level test, I think we should be testing the surface as experienced by the user as close as possible.

Another idea would be to try to split out the part of the code that does the task counting and test that separately more as an implementation detail to make sure the counts are correct. And then in the integration test to just measure the total time and span name/metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Final decision: I decided to stop testing the task count as it should be more an implementation testing more than integration testing. Also, this could be done in a future refactoring on InteractinTracker to test every specific module.

}
// Don't count periodic tasks like setInterval as they will be repeatedly
// called.
if (task.data.isPeriodic) return false;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why did you change this to ignore all periodic tasks? I would think that calls to setInterval could be pretty relevant to the work of user interactions.

One other thing that should be a TODO for later I think - if you have a periodic task with > 1 second of time, then I think it should be executed outside of the tracing zone. Otherwise, if it ends up doing some work in the future it will still be associated with that same older tracing zone.

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 found out that if we track periodic tasks, the interaction might not finish as they are called repeatedly, so we won't be able to determine the stability of the interaction.

// As there is another setTimeOut that completes the interaction, the
// span duraction is not precise, then only test if the interaction duration
// finishes within a range.
expect(rootSpan.duration).toBeLessThan(5);
Copy link
Contributor

Choose a reason for hiding this comment

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

Should you check a minimum time here too?

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 this case, this noop sync function does not have any logic.Then, the minimum time would be 0. I think that just checking the max time is fine.

spyOn(tracer, 'onEndSpan');
interaction.stopAndRecord();

expect(root.attributes['EventType']).toBe('click');
Copy link
Contributor

Choose a reason for hiding this comment

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

Should the test cases above for the fake user interactions also test these attributes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, Added.

@codecov-io
Copy link

codecov-io commented Jun 28, 2019

Codecov Report

Merging #104 into master will decrease coverage by 0.29%.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master   #104     +/-   ##
=======================================
- Coverage   96.29%    96%   -0.3%     
=======================================
  Files          26     28      +2     
  Lines         647    825    +178     
  Branches       83    124     +41     
=======================================
+ Hits          623    792    +169     
- Misses         24     33      +9
Impacted Files Coverage Δ
src/interaction-tracker.ts 93.54% <0%> (ø)
src/on-page-interaction-stop-watch.ts 100% <0%> (ø)
src/trace/model/tracing.ts 100% <0%> (+4.54%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a0d573f...6a3b59e. Read the comment docs.

constructor() {
// register the noop exporter to have an span event listener,
// helpful for testing.
this.tracer.registerSpanEventListener(this.exporter);
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you do this in the tests rather than here in the production code?

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

import { RootSpan, Tracer } from '@opencensus/web-core';
import { OnPageInteractionStopwatch } from '../src/on-page-interaction';

describe('OnPageInteraction', () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be 'OnPageInteractionStopwatch'? And should the file be something like test-on-page-interaction-stopwatch.ts?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

@draffensperger draffensperger merged commit 1b3a192 into census-instrumentation:master Jun 28, 2019
@crdgonzalezca crdgonzalezca deleted the testing branch July 24, 2019 15:58
RenaultAI pushed a commit to RenaultAI/opencensus-web that referenced this pull request Nov 20, 2019
While preparing for plugins, in a piecemeal fashion
firstly added some interfaces and a guide but since
the plugins proposal and implementation didn't make it
at the last minute, let's also remove the previous
code to avoid confusion.

Fixes census-instrumentation#104
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants