Pickle JS

Cucumber with Brine

Written By: @tolicodes at @hoverinc

Writing Tests Sucks...

  • So many frameworks
  • Different syntax and APIs to remember
  • Monotonous
  • Time Intensive
  • Lots of debugging
  • Drivers don't work
  • Difficult to set up
  • Way too slow

Enter Cypress

  • What Selenium should've been
  • Simple, beautiful, and works immediately
  • No extensions needed
  • Simple jQuery-like selectors
  • Super fast - no Selenium wrapper needed
  • Features: parallelization, recording, reporting

GAME CHANGERS

Time travel

Debug in Chrome DevTools

Live reload

Auto wait/sleep

Class-A stubbing

Recording test runs

Stable, complete and built from scratch

TIME TRAVEL

DEBUG IN DEVTOOLS

LIVE RELOAD

AUTO WAIT/SLEEP

Scenario: I should be able to search for a doc
    # An AJAX Search Happens Here
    When I type "recommended" into the "Search Input" in the "Header"
    Then I should see "Recommended Cypress Setup" in the "Search Result" in the "Header"
    
    # A redirect happens here
    When I click the "Search Result" in the "Header" containing "Recommended Cypress Setup"
    Then I should be redirected to "Recommended Cypress Setup"

CLASS-A STUBBING

// That's all you need to do to stub an endpoint!
cy.route('GET', '/users/*', {
  id: 1,
  name: 'toli'
});


// or put it in a file
cy.route('GET', '/users/*', 'users.json');

STABLE, COMPLETE & BUILT FROM SCRATCH

One Framework to Rule Them All

Stubbing - Assertions - Screenshot Diff - Recording -
Reporting - Test Runner - Browser Control

RECORDING TESTS

CUCUMBER

Write tests in plain English

Regular expression turns it into code

Scenario: I should be able to login
    When I open the "Login Page"
    And I type "toli@tolicodes.com" into the "Email Field"
    And I type "ilovepickles" into the "Password Field"
    And I click "Submit"

    Then I should see the "Login Successful" modal

As a developer, product manager, or QA  engineer,
I should be able to read and write feature tests without
programming knowledge

Enter PICKLE JS!

When I open "Some Page"
When I click "Some Element" inside "Some Container"
When I type "some text" into "Some Field"
When I scroll to the bottom of the page
When I drag "Some Element" above "Some Other Element"
When I take a snapshot named "Cheese"

Then I should be redirected to "the Home Page"
Then I should see 2 "Elements" containing "hello!"
Then I should see an "Element" in the "Container"
Then I should see a "red" background on the "Button"
Then I should see a "blue" border on the "Button"

95% of tests I write use the same patterns

Why write custom regular expressions every time?

CHALLENGES

No Javascript

Centralizing selectors

Selectors for styled components

Flexible grammar

Fixture & stubbing management

Enumerating elements

Sharing state

 

NO Javascript

{
  "Account Container": {
    "default": ".AccountSelection"
    "Title": ".Title"
    "Message": ".Message"
    "Accounts Select": ".AccountsSelect",
    "Next Button": "input:contains('Next')"
  },
  "Account Confirmation Modal": {
     "default": ".AccountConfirmationModal"
  }
}
Scenario: I select an account from the account modal

    When I select "PICKLE FARM" from the 
         "Account Select" in the "Account Modal"
    And  I click the "Next Button" in 
         the "Account Modal"

    Then I should see an 
         "Account Confirmation Modal"

Just write it in English!

Centralizing selectors

{
  "Account Container": {
    "default": ".AccountSelection"
    "Title": ".Title"
    "Message": ".Message"
    "Accounts Select": ".AccountsSelect",
    "Next Button": "input:contains('Next')"
  },
  "Account Confirmation Modal": {
     "default": ".AccountConfirmationModal"
  }
}

The first key concept of PickleJS is keeping all your selectors and page URLs in one place and only refer to them by human-readable names

{
  "Home": "/",
  "Users": "/users",
  "Sign Up": "/sign-up",
  "Messages": "/messages",
  "External Link": "http://extenal.link"
}

SELECTORS FOR
STYLED COMPONENTS

{
    "Account Selection Container": {
        "default": ".AccountSelection"
        "Title": ".Title"
        "Message": ".Message"
        "Accounts Select": ".AccountsSelect",
        "Next Button": "input:contains('Next')"
    }
}

Flexible Grammar

Some things sound awkward with a rigid structure

When I click the "Button"
When I click on the "Submit"
When I click "Submit"
When I click a "Button" 
When I click on "Click Me"
When I click on the "Button" in the "Footer"
     containing "Submit"
When I click the "Button" inside the "Modal"
When I click into the "Modal"
When I click inside of the "Modal"
... and much much more

Fixture/StubS Managment

Built for front-end integration testing (no API)


Everything is stubbed by default
(returns empty object with 200 Response)

 

router({
    '/users': '/users/getUsers',
    'GET /users/*': '/users/getUser',
    'PUT /users/*': '/users/putUsers',
    'POST /users/*': '/users/postUsers'
});

// Returns a success response with optional json
apiSuccess('/someUrl', 'GET', { hi: 'there' });

// Returns a 404 (default for GET)
apiNotFound('/someUrl');

Enumerating Elements

When I click the "seventh Button" in the "Modal"
And  I click the "last Button" in the "Modal"
And  I type "hello" in the "ten-thousandth Input"

Then I should see "hello" in the "ten-thousandth Output"

Uses the wordsToNumbers library to easily refer to ordinal elements

Sharing State

When('I login', () => {
   const username = 'toli';

   setState('username', username);

   cy.get('.loginInput').type(username);
});

Then('The username should match in the header', () => {
   cy.get('.header .username').should('contain', STATE['username']);
});

Easily share state in between Scenarios and Steps across files when using Cucumber/Pickle. WIP.

Example App

This website is the example application. Everything is tested using Cypress & Pickle

You can view the source for the website in the
Pickle JS Repo under /website

All the Cypress tests under website/cypress

DOCUMEntation site

Text

Start Simple

The Kitchen Sink

THE IMPACT

Save developer time - PMs write tests


Automatical documentation of features in English


Real TDD/BDD - PMs write all test cases first

THE PROPOSED DEV FLOW

Step 1: Product Manager defines Scenarios for a Feature in Pickle format

Step 2: Developer copies Scenarios to Integration tests in Pickle

Step 3: Developer develops the feature and all the scenarios in Storybook

Step 4: Developer writes unit tests in Jest

Step 5: Developer integrates the feature into the app

Step 6: PR must be approved by 2 team members and Integration/Unit tests must pass

Step 7: QA writes their own set of End to End Tests

Step 8: Deploy

The pickle Future vision

  1. Integration Testing Support: Ability to have Feature Tests (with Fixtures) and Integration Tests (with API) with a switch
  2. Framework Agnostic: Ability to carry over all your tests to other frameworks such as TestCafe or Selenium (maybe...)
  3. Mobile Support: Integration with Appium and BrowserStack
  4. WebGL Support: Ability to test Canvas based interactions via Screenshots. For example:
    When I drag the "File" into the "Trash Can"
    Then I should not see the "File"
  5. Selector File Builder Google Chrome plugin: Just click on the elements you want and it will build a selectors.json file. Eventually support building statements (recording actions)
  6. Pickle Playground & Editor Plugins: autocomplete and validation for phrases and selectors

We're Hiring!

Want to work on developing cool tools like Pickle.js?

 

Join our Team!

 

hover.to/jobs

Thank you to

The base framework that makes this possible

My employer who sponsored Pickle's development

The cucumber interpreter for Cypress

deck

By Anatoliy Zaslavskiy