DEV Community

Filip Hric
Filip Hric

Posted on

Test grepping in Cypress using Module API

If you are running hundreds of tests in Cypress, chances are you may want to run just a subset of them. There are several ways you can do this, and in this blog, I’d like to show you mine. If you are here just for the solution, feel free to scroll down to the end end of this blog where you’ll find the code.

As you probably know, to run all of your Cypress tests, you can type following command into your command line:

npx cypress run
Enter fullscreen mode Exit fullscreen mode

This will run all tests inside your current Cypress project. These are usually stored in integration folder. I usually like to create more folders inside to create separate test categories. Let’s say I have an api and ui folder. To run each one of them, I could create a separate npm scripts, so in my package.json I’d have the following:

{
  "scripts": {
    "cy:run": "npx cypress run",
    "cy:run:api": "npx cypress run --spec ./cypress/integration/api/*.ts",
    "cy:run:ui": "npx cypress run --spec ./cypress/integration/ui/*.ts"
  }
}
Enter fullscreen mode Exit fullscreen mode

These commands of course work well, but in order to run each of my test folders, I need to run a separate command. This is not such a big deal when there are only two folders, but if you have multiple of them, things can get complicated.

This is where Module API comes in super handy and I’ll show you how in a second. First, let’s write our run script with Module API. We’ll create a new cypress.js file in the root of our project and add following code inside:

const cypress = require('cypress');

cypress.run();
Enter fullscreen mode Exit fullscreen mode

This is pretty much the same thing as if we ran our npx cypress run command. But instead of this, we will run our command by typing this to our terminal:

node cypress.js
Enter fullscreen mode Exit fullscreen mode

To make things easier for us, let’s add this to our package.json scripts:

{
  "scripts": {
    "cy:run": "node cypress.js"
  }
}
Enter fullscreen mode Exit fullscreen mode

Our cypress.run() function can also take an options parameter. This way we can which tests should be run, similarly as we did with the --spec flag in our previous example. So let’s add options inside our function and specify a spec folder to run:

const cypress = require('cypress');

cypress.run({
  spec: './cypress/integration/api/*.ts',
});
Enter fullscreen mode Exit fullscreen mode

This property can also be an array, so we can run more folders and specify which ones we want to run:

const cypress = require('cypress');

cypress.run({
  spec: ['./cypress/integration/api/*.ts', './cypress/integration/ui/*.ts'],
});
Enter fullscreen mode Exit fullscreen mode

Now that we know all this, we can play inside our cypress.js file and apply any kind of logic we like.

Let’s say that instead of api and ui folder, I have folders named: list, detail, settings, login and signup. I want to be able to pick any number or combination of these, and at the same time be able to run all of them. To do this, we will add a module called yargs. This package enables us to create and work with our own command line options. We are going to add a --grep option, so that if we just want to run tests inside settings and login folders, we will call a script like this:

npm run cy:run -- --grep settings login
Enter fullscreen mode Exit fullscreen mode

To define our --grep option, we will add following to our cypress.js file:

const yargs = require('yargs');

const { grep } = yargs
  .option('grep', {
    type: 'array'
  }).argv;
Enter fullscreen mode Exit fullscreen mode

This will digest out --grep flag. In order to give it multiple arguments, we need do specify the type of the input (see type: 'array'). If you are unfamiliar with the { grep } syntax, go and check out my blog on destructuring, where I explain this in more detail.

Let’s finalize our script and pass these options to our cypress.run() command:

const cypress = require('cypress');
const yargs = require('yargs');

const { grep } = yargs
  .option('grep', {
    type: 'array',
    default: ['*']
  }).argv;

cypress.run({
  spec: grep.map(folder => `./cypress/integration/${folder}/*.ts`),
});

Enter fullscreen mode Exit fullscreen mode

We are mapping out all the folder names, so that when we call npm run cy:run -- --grep settings login our grep variable will be assigned the value of:

["settings", "login"]
Enter fullscreen mode Exit fullscreen mode

and our spec attribute will have the value of:

["./cypress/integration/settings/*.ts", "./cypress/integration/login/*.ts"]
Enter fullscreen mode Exit fullscreen mode

This way we can either pass names of our folders to our --grep argument, or we can omit the argument and run all of our tests.

It’s all just JavaScript so we can apply any logic we want. Instead of --grep we could maybe use --folder as the name of our parameter. We can go even further and create both --folder and --testFile flags to make our pick even more specific.

This has proven to be incredibly useful in my case. I can run just those tests I need to be ran instead of waiting for the whole test suite, but still maintain the option to run everything. Several CI providers enable you to run your pipeline on demand and specify a pipeline variable, which can be used exactly for setting up which tests you want to run.

I write blogs like these every week at filiphric.com and whenever I publish one, I send out an email, so you don’t miss it. You can also follow me on Twitter and reach out to me if you have any questions.

Top comments (0)