<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Davide Cantelli</title>
    <description>The latest articles on DEV Community by Davide Cantelli (@davide_cantelli).</description>
    <link>https://dev.to/davide_cantelli</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3714481%2Fbae17087-4429-4637-b071-4d6b625582cb.jpg</url>
      <title>DEV Community: Davide Cantelli</title>
      <link>https://dev.to/davide_cantelli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/davide_cantelli"/>
    <language>en</language>
    <item>
      <title>How to speed up slow Cypress Component Tests by running only affected tests in parallel</title>
      <dc:creator>Davide Cantelli</dc:creator>
      <pubDate>Fri, 16 Jan 2026 10:24:25 +0000</pubDate>
      <link>https://dev.to/davide_cantelli/how-to-speed-up-slow-cypress-component-tests-by-running-only-affected-tests-in-parallel-ndm</link>
      <guid>https://dev.to/davide_cantelli/how-to-speed-up-slow-cypress-component-tests-by-running-only-affected-tests-in-parallel-ndm</guid>
      <description>&lt;p&gt;In &lt;a href="https://www.trustlayer.io/" rel="noopener noreferrer"&gt;TrustLayer&lt;/a&gt; our Cypress component test suite had grown to hundreds of tests, and CI was taking over 20 minutes on every PR.&lt;/p&gt;

&lt;p&gt;Even for a one-line change.&lt;/p&gt;

&lt;p&gt;With the following approach we went &lt;strong&gt;from 22 minutes to an average of just 3 minutes — an 85% reduction&lt;/strong&gt; 💪&lt;/p&gt;

&lt;h2&gt;
  
  
  👆 Most tests are not affected
&lt;/h2&gt;

&lt;p&gt;Here's the thing: most of the time, your changes don't affect the majority of your test files. If you change &lt;code&gt;Button.tsx&lt;/code&gt;, you probably only need to run tests that actually import &lt;code&gt;Button.tsx&lt;/code&gt; — directly or indirectly.&lt;/p&gt;

&lt;p&gt;Yet, we were running everything on every PR.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✌️ So what?
&lt;/h2&gt;

&lt;p&gt;The basic idea to solve it is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find which files changed in the current PR&lt;/li&gt;
&lt;li&gt;Build a dependency graph of your codebase&lt;/li&gt;
&lt;li&gt;Find test files that depend on the changed files&lt;/li&gt;
&lt;li&gt;Run only those tests
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Changed: src/components/Button.tsx

Affected tests found:
Button.tsx → Button.cy.tsx ✓
Button.tsx → Card.tsx → Card.cy.tsx ✓
Button.tsx → Form.tsx → Form.cy.tsx ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running 3 tests instead of 200.&lt;/p&gt;

&lt;p&gt;Simple and clean.&lt;/p&gt;

&lt;p&gt;But do we really need to build this from scratch?&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 affected-tests-runner
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a href="https://claude.com/product/claude-code" rel="noopener noreferrer"&gt;Claude Code&lt;/a&gt;, I managed in just a few hours to create a tool that does exactly this and that would have taken me much longer without the help of AI. Here is: &lt;a href="https://www.npmjs.com/package/affected-tests-runner" rel="noopener noreferrer"&gt;affected-tests-runner&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;affected-tests-runner
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of running everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cypress run &lt;span class="nt"&gt;--component&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we now run only tests affected by the changes we have made:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx affected-tests run &lt;span class="nt"&gt;--test-command&lt;/span&gt; &lt;span class="s1"&gt;'npx cypress run --component --spec "{specs}"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Git diff&lt;/strong&gt; — Compares your branch against main/master to find changed files&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependency graph&lt;/strong&gt; — Uses &lt;a href="https://github.com/pahen/madge" rel="noopener noreferrer"&gt;madge&lt;/a&gt; to map all imports in your codebase&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace affected tests&lt;/strong&gt; — Finds test files that depend on changed code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run only those&lt;/strong&gt; — Passes the filtered spec list to Cypress&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  ⚡ Parallel execution in CI
&lt;/h2&gt;

&lt;p&gt;But there is more we can do.&lt;/p&gt;

&lt;p&gt;Because running fewer tests is great, but running them in parallel is even better, when your changes are affecting a lot of tests.&lt;/p&gt;

&lt;p&gt;Small change? 1 job, 5 tests, 2 minutes.&lt;br&gt;
Big refactor? 4 parallel jobs split the work.&lt;/p&gt;

&lt;p&gt;The basic idea is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Get the number of groups needed given a max number of tests for each group. For example, the following command might find 30 affected tests, which given a &lt;code&gt;max-tests=10&lt;/code&gt; will output &lt;code&gt;3&lt;/code&gt;:
&lt;code&gt;npx affected-tests-runner groups --max-tests 10&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Given the number of groups we can execute each group in parallel:
&lt;code&gt;npx affected-tests run --group 0 --total-groups 3&lt;/code&gt;
&lt;code&gt;npx affected-tests run --group 1 --total-groups 3&lt;/code&gt;
&lt;code&gt;npx affected-tests run --group 2 --total-groups 3&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In CI, this is typically automated with a matrix strategy. You can find some examples in the &lt;a href="https://github.com/cant89/affected-tests" rel="noopener noreferrer"&gt;README of the package&lt;/a&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  🔧 Works with any test runner
&lt;/h2&gt;

&lt;p&gt;The tool isn't Cypress-specific.&lt;br&gt;
It works with any test runner that accepts file paths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cypress Component
&lt;code&gt;--test-command 'npx cypress run --component --spec "{specs}"'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Jest
&lt;code&gt;--test-command 'npx jest {specs}'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Vitest
&lt;code&gt;--test-command 'npx vitest run {specs}'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Mocha
&lt;code&gt;--test-command 'npx mocha {specs}'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;...and any other similar test runner&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  😅 Are there any downsides?
&lt;/h2&gt;

&lt;p&gt;Well, yes. The analysis is file-level, not function-level. This might introduce some false positives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If &lt;code&gt;utils.ts&lt;/code&gt; exports 10 functions and you change one, all importers will be considered affected&lt;/li&gt;
&lt;li&gt;Barrel files (&lt;code&gt;index.ts&lt;/code&gt;) create wider blast radiuses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can mitigate this by using direct imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Avoid&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// Prefer&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/Button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But even with barrel files you will see huge improvements.&lt;/p&gt;

&lt;p&gt;Running a few extra tests is better than missing a broken one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;If you are struggling with slow test execution in the pipeline, this might be the solution for you.&lt;/p&gt;

&lt;p&gt;Please visit the repository page for much more details about how to use and configure it for your use case, and to get to see more examples.&lt;/p&gt;

&lt;p&gt;Happy coding! 💻&lt;/p&gt;




&lt;p&gt;Links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/affected-tests-runner" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/affected-tests-runner&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/cant89/affected-tests-runner" rel="noopener noreferrer"&gt;https://github.com/cant89/affected-tests-runner&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Credits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Photo by &lt;a href="https://medium.com/r?url=https%3A%2F%2Funsplash.com%2Fit%2F%40abeso%3Futm_source%3Dunsplash%26utm_medium%3Dreferral%26utm_content%3DcreditCopyText" rel="noopener noreferrer"&gt;Sebastian Bednarek&lt;/a&gt; on &lt;a href="https://medium.com/r?url=https%3A%2F%2Funsplash.com%2Fit%2Ffoto%2Ffoto-di-tastiera-da-gioco-nera-accesa-accanto-alla-tazza-i1M1nQD2l5w%3Futm_source%3Dunsplash%26utm_medium%3Dreferral%26utm_content%3DcreditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>react</category>
      <category>ci</category>
    </item>
  </channel>
</rss>
