callstack / reassure

Performance testing companion for React and React Native
https://callstack.github.io/reassure/
MIT License
1.27k stars 28 forks source link

[BUG] measure code is running under incorrect Node.js configuration #174

Closed sregg closed 2 years ago

sregg commented 2 years ago

I'm getting this message when running yarn reassure:

console.error ❌ Reassure: measure code is running under incorrect Node.js configuration. Performance test code should be run in Jest with certain Node.js flags to increase measurements stability. Make sure you use the Reassure CLI and run it using "reassure" command.

Same with npx reassure or yarn node --expose_gc $(yarn bin reassure).

reassure: v0.4.1 node: v14.17.6 yarn: v1.22.19 jest: v26.6.3 MBP M1 macOS: v12.4

thymikee commented 2 years ago

Is there any way you can share the repro we could download?

thymikee commented 2 years ago

Or could you share your package.json to the very least?

sregg commented 2 years ago

Here's our package.json:

{
  "name": "properly-app",
  "private": true,
  "scripts": {
    "start": "react-native start",
    "ios": "react-native run-ios",
    "ios:device": "react-native run-ios --device",
    "ios:iphone-SE": "react-native run-ios --simulator \"iPhone SE (3rd generation)\"",
    "android": "react-native run-android --appId ca.properly.ProperlyApp.debug",
    "adb:input": "adb shell input text",
    "test:e2e:ios:browserstack": "wdio run wdio-ios.conf.browserstack.js",
    "test:e2e:android:browserstack": "wdio run wdio-android.conf.browserstack.js",
    "test:e2e:ios:local": "wdio run wdio-ios.conf.local.js",
    "test:e2e:android:local": "wdio run wdio-android.conf.local.js",
    "typecheck": "tsc --noEmit -p . --skipLibCheck",
    "compile": "tsc --noEmit -p . --pretty",
    "format": "npm-run-all format:*",
    "format:js": "prettier --write \"app/**/*.js\" \"test/e2e/**/*.js\" \"wdio.conf.local.js\"",
    "format:json": "prettier --write \"app/**/*.json\" \"fixtures/**/*.json\" \"test/e2e/**/*.json\"",
    "format:md": "prettier --write \"**/*.md\"",
    "format:ts": "prettier --write \"app/**/*.ts{,x}\"",
    "check-files-format": "prettier --check",
    "check-format": "npm-run-all check-format:*",
    "check-format:js": "prettier --check \"app/**/*.js\"",
    "check-format:json": "prettier --check \"app/**/*.json\" \"fixtures/**/*.json\"",
    "check-format:md": "prettier --check \"**/*.md\"",
    "check-format:ts": "prettier --check \"app/**/*.ts{,x}\"",
    "lint": "eslint index.js app storybook test --fix --ext .js,.ts,.tsx",
    "patch": "patch-package",
    "storybook": "start-storybook -p 9001 -c ./storybook",
    "test": "jest",
    "test:watch": "jest --watch",
    "adb": "adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001 && adb reverse tcp:8081 tcp:8081",
    "postinstall": "node ./bin/postInstall",
    "build-ios": "react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios",
    "build-android": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
    "clean": "react-native-clean-project",
    "clean-all": "npx react-native clean-project-auto",
    "prepare": "husky install",
    "pod-update": "cd ios && pod repo update && cd .."
  },
  "dependencies": {
    "@aws-amplify/auth": "^4.5.9",
    "@aws-amplify/core": "^4.5.9",
    "@freakycoder/react-native-progressive-fast-image": "^0.2.5",
    "@goproperly/product-schema": "^4.10.0",
    "@goproperly/web-util": "^7.1.0",
    "@gorhom/bottom-sheet": "^4.4.2",
    "@hookform/resolvers": "^2.9.7",
    "@iterable/react-native-sdk": "^1.3.2",
    "@ptomasroos/react-native-multi-slider": "^2.2.2",
    "@react-native-async-storage/async-storage": "^1.17.7",
    "@react-native-clipboard/clipboard": "^1.10.0",
    "@react-native-community/geolocation": "^2.1.0",
    "@react-native-community/netinfo": "^9.3.0",
    "@react-navigation/bottom-tabs": "^6.3.2",
    "@react-navigation/devtools": "^6.0.8",
    "@react-navigation/native": "~6.0.11",
    "@react-navigation/native-stack": "^6.7.0",
    "@react-navigation/stack": "~6.2.2",
    "@segment/analytics-react-native": "^2.3.2",
    "@segment/sovran-react-native": "^0.2.8",
    "@sentry/react-native": "^4.3.1",
    "@types/supercluster": "^7.1.0",
    "add": "^2.0.6",
    "algoliasearch": "^4.13.1",
    "amazon-cognito-identity-js": "^5.2.10",
    "apisauce": "2.1.5",
    "axios": "^0.27.2",
    "date-fns": "^2.28.0",
    "i18n-js": "3.9.2",
    "jotai": "^1.7.4",
    "libphonenumber-js": "^1.10.11",
    "lodash.isequal": "^4.5.0",
    "native-base": "^3.4.8",
    "react": "17.0.2",
    "react-hook-form": "^7.34.0",
    "react-native": "0.67.2",
    "react-native-awesome-gallery": "^0.3.5",
    "react-native-collapsible": "^1.6.0",
    "react-native-fast-image": "^8.5.11",
    "react-native-floating-label-input": "^1.4.2",
    "react-native-gesture-handler": "^2.5.0",
    "react-native-inappbrowser-reborn": "^3.7.0",
    "react-native-linear-gradient": "^2.6.2",
    "react-native-maps": "^1.1.0",
    "react-native-mmkv": "^2.4.3",
    "react-native-permissions": "^3.6.1",
    "react-native-reanimated": "^2.9.1",
    "react-native-restart": "^0.0.24",
    "react-native-safe-area-context": "^4.3.1",
    "react-native-screens": "3.15.0",
    "react-native-shadow-2": "^7.0.5",
    "react-native-svg": "^12.3.0",
    "react-native-triangle": "^0.0.9",
    "react-native-url-polyfill": "^1.3.0",
    "react-native-version-info": "^1.1.1",
    "react-native-webview": "^11.23.0",
    "react-number-format": "^4.9.3",
    "react-query": "^3.39.1",
    "rn-android-keyboard-adjust": "^2.0.0",
    "supercluster": "^7.1.5",
    "use-deep-compare-effect": "^1.8.1",
    "validate.js": "0.13.1",
    "zod": "^3.17.9"
  },
  "devDependencies": {
    "@babel/core": "^7.12.9",
    "@babel/plugin-proposal-decorators": "7.12.1",
    "@babel/plugin-proposal-numeric-separator": "^7.18.6",
    "@babel/plugin-proposal-optional-catch-binding": "7.12.1",
    "@babel/runtime": "^7.12.5",
    "@react-native-community/cli-platform-ios": "^6.2.0",
    "@storybook/react-native": "5.3.23",
    "@storybook/react-native-server": "5.3.23",
    "@testing-library/jest-native": "^4.0.11",
    "@testing-library/react-hooks": "^8.0.1",
    "@testing-library/react-native": "^11.0.0",
    "@types/i18n-js": "3.0.3",
    "@types/jest": "26.0.19",
    "@types/react": "17.0.37",
    "@types/react-native": "0.66.9",
    "@types/react-test-renderer": "17.0.1",
    "@typescript-eslint/eslint-plugin": "5.18.0",
    "@typescript-eslint/parser": "5.18.0",
    "@wdio/appium-service": "^7.23.0",
    "@wdio/browserstack-service": "^7.23.0",
    "@wdio/cli": "^7.23.0",
    "@wdio/local-runner": "^7.23.0",
    "@wdio/mocha-framework": "^7.23.0",
    "@wdio/spec-reporter": "^7.23.0",
    "appium": "^1.22.3",
    "babel-jest": "26.6.3",
    "babel-loader": "8.2.2",
    "eslint": "8.12.0",
    "eslint-config-prettier": "8.5.0",
    "eslint-config-standard": "16.0.3",
    "eslint-import-resolver-typescript": "^2.7.1",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-node": "11.1.0",
    "eslint-plugin-promise": "6.0.0",
    "eslint-plugin-react": "7.29.4",
    "eslint-plugin-react-hooks": "4.4.0",
    "eslint-plugin-react-native": "4.0.0",
    "fbjs-scripts": "3.0.0",
    "husky": "^7.0.0",
    "jest": "26",
    "jest-circus": "26",
    "jest-expo": "^44.0.1",
    "jetifier": "1.6.6",
    "lint-staged": ">=10",
    "msw": "^0.41.0",
    "npm-run-all": "4.1.5",
    "patch-package": "6.2.2",
    "postinstall-prepare": "1.0.1",
    "prettier": "2.2.1",
    "query-string": "^7.0.1",
    "react-dom": "^17.0.2",
    "react-native-clean-project": "^3.6.3",
    "react-native-flipper": "^0.164.0",
    "react-native-flipper-performance-plugin": "^0.3.1",
    "react-native-mmkv-flipper-plugin": "^1.0.0",
    "react-query-native-devtools": "^4.0.0",
    "reassure": "^0.4.1",
    "solidarity": "2.3.1",
    "ts-jest": "26",
    "typescript": "4.2.3"
  },
  "resolutions": {
    "react-devtools-core": "4.24.3"
  },
  "lint-staged": {
    "*.{ts,tsx,js,jsx}": "eslint --cache",
    "*.{ts,tsx,js,jsx,md,json}": "prettier --check"
  }
}

If you don't spot anything interesting I'll try to create a minimum reproducible example.

thymikee commented 2 years ago

It's probably unrelated but you don't seem to have react-test-renderer@17.0.2 as a dependency, only types are there. Mind adding it?

sregg commented 2 years ago

It's probably unrelated but you don't seem to have react-test-renderer@17.0.2 as a dependency, only types are there. Mind adding it?

For some reason we have it with jest-expo (we used Ignite to start the project but we're not using Expo).

jest-expo@^44.0.1:
  version "44.0.1"
  resolved "https://registry.npmjs.org/jest-expo/-/jest-expo-44.0.1.tgz"
  integrity sha512-pGncycmLBlg2rOiZjdWGFujlVe3X+SHutKN42rZPoG3zOvv66/E0VpSQxPyn3DN3JCNKpWlK7CkwpCweg0qKtA==
  dependencies:
    "@expo/config" "^6.0.6"
    "@jest/create-cache-key-function" "^26.6.2"
    babel-jest "^26.6.3"
    find-up "^5.0.0"
    jest-watch-select-projects "^2.0.0"
    jest-watch-typeahead "0.6.4"
    json5 "^2.1.0"
    lodash "^4.17.19"
    react-test-renderer "~17.0.1"
sregg commented 2 years ago

Here's our jest.config.js

const { defaults: tsjPreset } = require('ts-jest/presets');

module.exports = {
  ...tsjPreset,
  preset: 'jest-expo',
  globals: {
    'ts-jest': {
      babelConfig: true,
    },
  },
  transformIgnorePatterns: [
    '<rootDir>/node_modules/(react-clone-referenced-element|@react-native-community|react-navigation|@react-navigation/.*|@unimodules/.*|native-base|react-native-code-push)',
  ],
  testPathIgnorePatterns: ['<rootDir>/node_modules/', '/e2e', '@react-native'],
  testEnvironment: 'jsdom',
  setupFiles: ['<rootDir>/test/setup.ts'],
  setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
  moduleNameMapper: {
    '\\.(jpg|jpeg|png|svg)$': '<rootDir>/test/mock-file.ts',
    '\\.(css|scss)$': 'identity-obj-proxy',
  },
};
thymikee commented 2 years ago

What if you replaced jest-expo preset with react-native? Would be great if you tried running our examples and see if there's anything in your environment that gets in the way

sregg commented 2 years ago

Removing jest-expo and setting preset: react-native worked 🎉 The test was very slow though (200s)

simonreggiani@Simons-MacBook-Pro-2 mobile-app % yarn reassure
yarn run v1.22.19
$ /Users/simonreggiani/dev/mobile-app/node_modules/.bin/reassure

❇️  Running current performance tests:

 PASS  test/performance/search-filters-screen.perf-test.tsx (202.485 s)
  Search Filters Screen Performance
    ✓ Select 3br (18517 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        203.02 s
Ran all test suites.

✅  Written current performance measurements to .reassure/current.perf
🔗 /Users/simonreggiani/dev/mobile-app/.reassure/current.perf

Baseline performance file does not exist, run 'reassure --baseline' on your baseline code branch to create it.

✨  Done in 204.20s.
sregg commented 2 years ago

Second run is only 24s.

thymikee commented 2 years ago

We need to investigate what's there in jest-expo preset that prevents Node from reading global.gc. Glad it worked for you!