How to Perform Visual Testing for React Native Components
What You Need Before Starting Visual Testing
So you've built a React Native app. It works on your phone, passes unit tests, and your teammates say it looks fine. But then a new build goes out, and suddenly a button is misaligned on older iPhones. Text overlaps an image on Android tablets. A color change you didn't notice breaks the entire onboarding flow.
This is where visual testing for React Native comes in. It catches those UI bugs that traditional tests miss. Honestly, most teams skip this step until something breaks in production. Don't be that team.
In this guide, you'll learn exactly how to set up visual testing for your React Native components, step by step. We'll cover tools, writing tests, CI integration, and keeping baselines sane. By the end, you'll have a system that catches visual regressions before they reach users.
Prerequisites for Visual Testing in React Native
Before we jump in, make sure you have these basics covered:
- A React Native project – either Expo or bare workflow works fine. If you're starting fresh, Expo is easier for testing.
- A device or emulator for taking screenshots. You can use iOS Simulator, Android Emulator, or a physical device.
- A testing framework like Jest or Detox to run your tests and capture component snapshots. Jest is the most common choice for React Native.
- A visual testing tool that integrates with React Native. We'll use Sherlo in this guide because it's built specifically for React Native and handles the tricky parts (animations, async rendering) out of the box. Other options include Percy and Applitools, but Sherlo's React Native integration is tighter.
Got all that? Good. Let's get our hands dirty.
Step 1: Set Up a Visual Testing Tool for React Native
This is where you actually install and configure the tool. Most visual testing tools follow a similar pattern: add an SDK, configure it, then link it to a dashboard where you'll review screenshots.
Integrating Sherlo with Your React Native App
Let's walk through Sherlo specifically – it's the smoothest React Native integration I've used.
First, install the package:
npm install @sherlo/react-native
Then, wrap your app component with Sherlo's provider. This is usually done in your root App.js or index.js file:
import { SherloProvider } from '@sherlo/react-native';
export default function App() {
return (
<SherloProvider>
<YourApp />
</SherloProvider>
);
}
Next, configure the tool to capture screenshots of your components in different states. You'll define these states in your test files – more on that in Step 2.
Pro tip: Link your app to Sherlo's cloud dashboard. This is where you'll see all your screenshots, compare them against baselines, and approve or reject changes. The dashboard URL is provided when you create a project on Sherlo's site.
Finally, define baseline images. These are the "correct" screenshots that future tests will compare against. Sherlo captures these automatically when you run your tests for the first time.
Step 2: Write Visual Tests for Individual Components
Now the fun part – writing tests that actually catch visual bugs. The goal here is to render each component with realistic data and capture what it looks like.
Capturing and Comparing Component Snapshots
Here's a simple test for a UserCard component using Jest and Sherlo:
import { render } from '@testing-library/react-native';
import { createVisualTest } from '@sherlo/react-native';
import UserCard from '../UserCard';
test('UserCard renders correctly', async () => {
const { getByTestId } = render(
<UserCard name="Jane Doe" avatar="https://example.com/avatar.jpg" />
);
await createVisualTest(getByTestId('user-card'), {
name: 'UserCard-default',
});
});
Key things to know:
- Use mock data that represents real scenarios. Don't just pass empty strings – your users won't see empty strings.
- Trigger state changes. Test the component when it's loading, when data is present, and when there's an error. For example, a button press that shows a loading spinner.
- Automatically capture screenshots and compare them against stored baselines. Sherlo does this comparison in the cloud and highlights pixel differences.
- Set a threshold for pixel differences. A 0.1% threshold allows for minor anti-aliasing variations across devices without failing tests. This prevents flaky results on different screen resolutions.
Warning: Don't skip testing edge cases. What happens when a user's name is 50 characters long? What about an empty list? These are exactly the scenarios that cause visual regressions in production.
Step 3: Integrate Visual Tests into CI/CD Pipeline
Manual visual testing is better than nothing, but automated visual testing is where you get real value. You want every commit to automatically check for UI regressions.
Running Visual Tests Automatically on Every Commit
Here's how to set it up with GitHub Actions:
- Create a workflow file (e.g.,
.github/workflows/visual-tests.yml) - Add a step that runs your visual tests after unit tests pass. This saves time – no point running visual tests if unit tests are failing.
- Configure Sherlo to upload screenshots to its cloud dashboard automatically.
- Set up automatic approval for unchanged baselines. If nothing changed, the test passes.
- For detected changes, require manual review. A team member checks the diff and approves or rejects it.
Here's a minimal GitHub Actions example:
jobs:
visual-tests:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- run: npm ci
- run: npx detox build --configuration ios
- run: npx detox test --configuration ios
- run: npx sherlo test
env:
SHERLO_API_KEY: ${{ secrets.SHERLO_API_KEY }}
Practical tip: Run visual tests on the same device type every time. If your CI uses iPhone 14 but your developers use iPhone 15 Pro, you'll get different screenshots. Standardize on one device for consistency.
Step 4: Review and Update Baselines Regularly
Baselines aren't set in stone. When you intentionally change a component's design, you need to update the baseline so future tests compare against the new look.
Managing Visual Test Baselines Over Time
Here's the workflow:
- When you make a deliberate UI change, commit it and push to a branch.
- The CI runs visual tests. They fail because the screenshots don't match the old baselines.
- Go to Sherlo's dashboard. You'll see the diff highlighted – exactly what changed (color, layout, text size).
- Review the diff with your team. Is this the expected change? If yes, approve the new screenshots as the new baseline.
- Merge your branch. Future tests will compare against the updated baselines.
This is where Sherlo shines. Its diff viewer shows you pixel-level changes with color overlays. Red means removed, green means added. You can zoom in on specific areas. Honestly, this saves hours of "Is this a real bug or just a rendering difference?" conversations.
Warning: Never approve baselines without reviewing the diff. It's tempting to click "Approve All" when you're in a hurry. That's how regressions sneak in. Make it a rule: two eyes on every diff.
Best Practices for Visual Testing in React Native
After setting up visual regression testing for several React Native projects, here are the practices that actually work (and the ones that don't).
Tips to Avoid Flaky Visual Tests
Flaky tests are the enemy of automated testing. A test that fails randomly erodes trust in the whole system. Here's how to keep yours reliable:
- Freeze animations and async operations before taking screenshots. Use
InteractionManager.runAfterInteractionsor wait for specific elements to appear. An animation that's halfway through will cause false failures. - Test on multiple device sizes and orientations. A component that looks perfect on an iPhone 15 might break on an iPhone SE in landscape mode. Sherlo lets you define multiple viewport sizes in one test run.
- Combine visual testing with unit and integration tests. Visual tests catch UI bugs, not logic bugs. Use unit tests for business logic and integration tests for data flow. Together, they give you comprehensive coverage.
- Use consistent mock data. Random data (like faker-generated names) will change every test run, causing false diffs. Use static mock data files.
- Set timeouts appropriately. Visual tests take longer than unit tests. Give them 30-60 seconds per test, especially on CI where emulators are slower.
One more thing: If you're wondering what is visual testing exactly and how it differs from unit testing – think of it this way. Unit tests check if a function returns the right value. Visual tests check if the UI looks right. Both are necessary, but they catch completely different types of bugs.
Summary: How to Do Visual Testing for React Native
Let's recap the steps so you can implement this right away:
- Set up a visual testing tool – Install Sherlo (or another tool), configure it, and link to the dashboard. Define your first baseline images.
- Write visual tests – For each component, render it with mock data in different states. Capture screenshots and set a pixel-difference threshold.
- Integrate with CI/CD – Add visual tests to your pipeline after unit tests. Upload screenshots to the cloud and require manual review for changes.
- Manage baselines – When you make intentional UI changes, approve new baselines in the dashboard. Always review diffs with your team.
- Follow best practices – Freeze animations, test multiple devices, and combine with other testing types for full coverage.
Visual testing isn't optional anymore. With React Native apps running on dozens of device sizes and OS versions, manual QA can't catch everything. Automate it, and you'll sleep better knowing your UI won't break on the next release.
Najczesciej zadawane pytania
What is visual testing in React Native?
Visual testing in React Native is a quality assurance technique that involves capturing screenshots of app components and comparing them to baseline images to detect visual regressions. It ensures the UI looks as expected across different devices, screen sizes, and states, catching unintended changes like layout shifts, color mismatches, or missing elements.
What tools are commonly used for visual testing in React Native?
Popular tools include Percy (integrates with CI/CD), Storybook (with addons like Chromatic), Applitools (uses AI for visual comparisons), and Jest-based solutions like jest-image-snapshot. These tools automate screenshot capture and comparison, making it easier to maintain visual consistency.
How do you set up visual testing for a React Native component?
First, install a visual testing tool (e.g., Percy or jest-image-snapshot). Then, write a test that renders the component with specific props and states, capture a screenshot, and compare it to a stored baseline. For example, using jest-image-snapshot, you call `toMatchImageSnapshot()` after rendering the component in a test environment. Integrate the tool with your test runner and CI pipeline for automated checks.
What are the main benefits of visual testing for React Native apps?
Visual testing catches UI regressions that unit tests might miss, such as styling bugs, layout issues on different devices, or text overflow. It improves code review efficiency by providing visual diffs, ensures cross-platform consistency (iOS vs. Android), and reduces manual QA effort by automating screenshot comparisons.
What challenges might arise when performing visual testing in React Native?
Challenges include handling platform-specific differences (e.g., font rendering, shadow effects), managing flaky tests due to dynamic data or animations, and maintaining baseline images as the UI evolves. Additionally, setting up a consistent test environment (e.g., simulator/emulator configurations) and dealing with image resolution variations across devices can be tricky.