-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
test(node): Add Node SDK integration test structure. #4694
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
Conversation
size-limit report
|
3e4b5dd
to
fb154c9
Compare
lookin good 👍 in our daily it came up if you think this would be easily re-used for nextjs? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, could you write a README similar to what you did for the playwright tests here?
It can be very WIP - just so we have some of this in code that we can iterate on (also makes future git blames easier instead of digging through PR descriptions)
More fleshed out review incoming
I think so, it's very similar to the current next server tests after all.
Sure, will do today. 👍 |
I think it's a valid concern. I also have never liked the fact that snapshots force you to assert on everything, when any given test is probably only testing a subset (and it's a lot harder to tell what subset because of all of the noise). So I try to avoid them if at all possible.
As we discussed this morning (and which I'm including here for posterity), IMHO testing against our built code isn't really something we need to worry about on the node side. With the browser SDK, we're spinning up all sorts of variations when we build bundles (including ones which explicitly delete some of the code), and they build into something barely human-readable (making them really hard to sanity-check), so testing against them gives us a sense of security we wouldn’t get otherwise. None of that applies to Node, though, so I think our collective building, reviewing, and maintenance time is better spent elsewhere.
Also from our conversation this morning, I think it's safe to mock the DB methods, rather than worrying about trying to spin up live databases. The thing we're trying to test is whether or not we start and stop spans when we should, and whether we're collecting the correct metadata along the way, but not what happens in between. (Put another way, we instrument the call to the DB, not the DB query itself, so as long as we test that, we're good.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking good so far!
I wonder, though - is there a way to avoid having the relevant code spread over four separate files (some of which seem pretty boilerplate), with each test having to live in a separate folder? I know that this structure is similar to what we have on the browser side, but I've found with those that I end up doing a whole lot of clicking around just to look at all the pieces of one test. What do you think?
const url = await runServer(__dirname); | ||
const requestBody = await getEventRequest(url); | ||
|
||
expect(updateForSnapshot(requestBody)).toMatchSnapshot(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Following up on my comment above re: snapshots, I think it's enough if we assert on the exception, similar to how Kamil did it in the nextjs integration tests here:
sentry-javascript/packages/nextjs/test/integration/test/client/errorClick.js
Lines 9 to 18 in ba14cc5
expectEvent(requests.events[0], { | |
exception: { | |
values: [ | |
{ | |
type: 'Error', | |
value: 'Sentry Frontend Error', | |
}, | |
], | |
}, | |
}); |
All we really want to prove is that calling captureException
results in an error event being sent. The rest (should) be covered by our unit tests.
{ | ||
"extends": "../../tsconfig.json", | ||
"compilerOptions": { | ||
"allowSyntheticDefaultImports": true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"allowSyntheticDefaultImports": true, |
Per the TS docs, turning on esModuleInterop
also automatically turns on allowSyntheticDefaultImports
.
"compilerOptions": { | ||
"allowSyntheticDefaultImports": true, | ||
"esModuleInterop": true, | ||
"moduleResolution": "node", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"moduleResolution": "node", |
This is inherited from @sentry-internal/typescript
via the repo's root-level tsconfig.
"moduleResolution": "node", |
"allowSyntheticDefaultImports": true, | ||
"esModuleInterop": true, | ||
"moduleResolution": "node", | ||
"noEmit": false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"noEmit": false, |
This should be the tsc
default.
"esModuleInterop": true, | ||
"moduleResolution": "node", | ||
"noEmit": false, | ||
"strict": true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"strict": true, |
This is also inherited:
"strict": true, |
"moduleResolution": "node", | ||
"noEmit": false, | ||
"strict": true, | ||
"types": ["jest"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"types": ["jest"] | |
"types": ["jest", "node"] |
tsconfig inheritance is unfortunately not additive, so we have to re-specify node here.
fce6e20
to
8862a29
Compare
release: '1.0', | ||
}); | ||
|
||
Sentry.captureMessage('Message'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's call this suites/public-api/capture-message/...
to better match the playwright tests?
release: '1.0', | ||
}); | ||
|
||
Sentry.captureException('Captured Error'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's try to match how this is often used by users.
Sentry.captureException('Captured Error'); | |
Sentry.captureException(new Error('Captured Error')); |
const [envelopeHeaderString, itemHeaderString, itemString] = body.split('\n'); | ||
|
||
return { | ||
envelopeHeader: JSON.parse(envelopeHeaderString), | ||
itemHeader: JSON.parse(itemHeaderString), | ||
item: JSON.parse(itemString), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is dangerous because it assumes only 1 item, while envelopes can have multiple items. Can we work around this? See:
sentry-javascript/packages/utils/test/testutils.ts
Lines 15 to 17 in ebc9da5
export function parseEnvelope(env: string): Array<Record<any, any>> { | |
return env.split('\n').map(e => JSON.parse(e)); | |
} |
import { assertSentryTransaction, getEnvelopeRequest, runServer } from '../../../utils'; | ||
|
||
test('should send a manually started transaction.', async () => { | ||
const url = await runServer(__dirname); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so this starts a new server for each test. Could that get expensive? Could we somehow re-use the same server instance?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My initial idea was to make servers pluggable just like template
s in Playwright tests, so we can write tests for specific server configurations. Would that make sense to check the overall performance and revisit this when we're writing a bit more complex tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that’s fine with me - we can def come back and explore further!
I think for Node tests, we might not need separate Still not looking great as we still have a separate folder for each test / scenario. The reason for that is when I wrote more than one test in a set, Jest stopped logging the pure error source (like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still not looking great as we still have a separate folder for each test / scenario
I think this is fine - we can come back and re-evaluate if it's such a pain.
@onurtemizkan mind rebasing? Let's get this initial version in and then we can iterate as we go forward. |
CHANGELOG.md
Outdated
|
||
This release fixes a bug from 6.19.0 causing type import errors in most JS SDKs. | ||
|
||
fix(types): Point to type definitions in dist folder [#4745](https://github.com/getsentry/sentry-javascript/pull/4745) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be from a bad merge commit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops yes.
89a50de
to
49ab765
Compare
@@ -0,0 +1,12 @@ | |||
import { assertSentryTransaction, getEnvelopeRequest, runServer } from '../../../utils'; | |||
|
|||
test.skip('should send a manually started transaction when @sentry/tracing is imported using namespace import.', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Skipping this test for now, we can re-enable it with the PR to fix #4731.
Taking it down from 4 files to 2 is already def an improvement. My main reasons for asking about this were 1) the test tests the results of whatever happens in the scenario, and it's easier to reason about that cause and effect if you can see them both at once, and 2) (less important) I often find it helpful to just scan down the list of test titles ( I can see why they're currently in two files, though, so |
As part of #4694, which adds integration tests for node, a change was made to the repo-level `yarn test` command, in order to skip running the new tests. The new version of the command was missing a `--ignore` flag, though, causing the command to error out. This adds the missing flag.
This PR introduces a structure for integration testing Node SDK,
Summary:
init
,subject
andserver
scripts are put together, to start a test scenario. My first attempt was to bundle them with Webpack and run on a separate thread, but it's not compatible with hownock
works (requires to patch and listen on the same thread).jest
snapshots. Random or platform-specific properties are patched withexpect.any(...)
. I'm still not sure about this approach as it can be too fragile with even small updates on SDK (especially stack-trace snapshots).cjs
/esm
builds are separately tested, but we transformesm
builds tocjs
beforehand withbabel
, asjest
still doesn't supportesm
modules natively.This implementation is very basic and there might be many improvements required when we actually start writing tests. It would be great if I can get feedback and reviews about the approach taken here, so we can build the rest on top of that.
cc: @AbhiPrasad, @lobsterkatie
Fixes: #4260