Use Gherkin file in your unit tests with vitest
Tags: vitest, gherkin, typescript
Published: 2023-08-04 22:57:52

Hi everybody, this is my first post, I hope you will like it ;)

In my company we are migrating some projects from jest to vitest. Everything is ok except one thing : the use our Gherkin feature file in our unit tests.

To be simple we use [Gherkin](https://cucumber.io/docs/gherkin/reference/) to describe what we vill do : new feature, fix a bug, improvement etc

For example, I take it on Gherkin website : 

```
Feature: Guess the word
    Scenario: Breaker joins a game
        Given the Maker has started a game with the word "silky"
        When  the Breaker joins the Maker's game
        Then  the Breaker must guess a word with 5 character
```

When we use jest, we use [jest-cucumber](https://github.com/bencompton/jest-cucumber) but currenly we haven't an alternative for vitest.

So this week I worked on a new project : [vitest-cucumber](https://github.com/amiceli/vitest-cucumber).

## Why ?

Feature file are very important for us so when we run unit tests we want to know if we forgot a scenario or a scenario step or type wrong scenario title.

A good advantage for us, if one day some code break a unit test like `it('should join a game')`.

`Error Scenario: Breaker joins a game > When failed ` is a better error message ;)

## How it works

In [vitest-cucumber](https://github.com/amiceli/vitest-cucumber), I create a parser who reads feature file line by line and return a `Feature` class.

`Feature` can contains multiple `Scenario` and a `Scenario` can contains multiple steps.

And I create `describeFeature` when to write unit test for a Feature, Scenario and steps.

## An example

An example of feature file : 

```
Feature: Improve my unit tests
    Scenario: Use vitest-cucumber in my unit tests
        Given Developer using feature file
        And   Using vitest-cucumber
        When  I run my unit tests
        Then  I know if I forgot a scenario
```

And an example of unit tests using vitest : 

```typescript
import { loadFeature, describeFeature } from '@miceli/vitest-cucumber'
import { expect } from 'vitest'

const feature = await loadFeature('path/to/my/file.feature')

describeFeature(feature, ({ Scenario }) => {
            
    Scenario('Use vitest-cucumber in my unit tests', ({ Given, When, Then, And }) => {
        Given('Developer using feature file', () => {
            // ...
        })
        And('using vitest-cucumber', () => {
            // ...
        })
        When('I run my unit tests', () => {
            // ...
        })
        Then('I know if I forgot a scenario', () => {
            // ...
        })
    })

})
```

### `describeFeature`

Run unit test for a Feature. This function uses `describe` vitest function and provide `Scenario`

`describeFeature` uses `afterAll`, at the end it checks if you missed a scenario or typed a wrong scenario name.

### `Scenario`

This function also uses `describe` but provide multiple function for scenario steps.

It also uses `afterAll` but checks if you forgot a step or write a wrong step name.

### `When`, `Then` etc

This function uses `test` vitest function.
So this is here to code our `expect` etc.

## Now

I opened an [issue](https://github.com/vitest-dev/vitest/issues/3892) on Vitests, to know their opinion and share my project.

I still work on it to improve error messages when unit tests failed and I hope for some feedback to improve this project.

Currently I code scenarios and steps but Gherkin is very powerful : tags, value etc. I've lot of work and I like it ;)

Thanks you, I hope you like this post.