Upgrade to Pro — share decks privately, control downloads, hide ads and more …

End to end testing Single Page Apps & APIs with...

End to end testing Single Page Apps & APIs with Cucumber.js and Puppeteer (Ember London meetup June 2018)

Here are the slides from my talk at Ember London meetup June 2018 on End-to-end testing Single Page Apps & APIs with Cucumber.js and Puppeteer

Paul Jensen

June 14, 2018
Tweet

More Decks by Paul Jensen

Other Decks in Programming

Transcript

  1. End-to-end Testing Single Page Apps & APIs with Cucumber.js &

    Puppeteer London Ember Meetup June 2018
  2. Such as how to do E2E testing on apps that

    were split into SPAs and APIs
  3. Step 2 Create a folder in your app called “features”.

    We will put cucumber-related files and folders in here. features
  4. Step 3 Meet with your product owner and talk about

    a feature to implement. Talk about how that feature works from the perspective of the user, and write notes.
  5. Step 4 Create a file in the features folder, say

    for example delete_user.feature. Type the notes from earlier into that feature file, and write them in a format like the example here.
  6. Step 5 The feature file we created can be parsed

    by Cucumber. Go to the terminal, and run this command on the right. Cucumber will look for files in the features folder, execute them, and print out results.
  7. Step 5 - step definitions When executing the feature file,

    Cucumber will try to match the lines in the feature file to step definition functions. If no step definition functions are found, it will print out example code to insert. step definition files
  8. Step 5 - step definitions When a step contains one

    or more words in quotes, Cucumber’s parser will extract out that quote and pass it to the step definition function as a variable. It also does this for numbers as well.
  9. Step 6 Create a folder called “step_definitions” inside of the

    features folder. Then create a file, say for example “common_steps.js” inside the step_definitions folder, and put the step definitions code in there. Cucumber will find this code and execute it upon subsequent test runs step_definitions common_steps.js
  10. Step 7 We fill in the step definition functions with

    code that performs an action, such as: - Clicking on a button in the web app - Checking that a user is logged into an app - Querying the database to check that a record was entered into a table
  11. Step 7 Our tests should fail, but as we write

    the application’s code, they will start to pass. We can then use this safety net to refactor the code and make bigger changes to the application. Fail Pass Change
  12. A Node.js library that provides a high- level API for

    controlling Google Chrome (or Chromium) via the DevTools protocol
  13. Puppeteer can run the web browser in either full mode

    (browser windows), or headless mode (no browser windows)
  14. You can use it to… • Take screenshots of web

    sites • Create PDF files from web pages • Crawl a SPA and generate pre-rendered content, such as scraping a major ticketing site. • Power web spiders that fill in forms automatically • Get a timeline trace of a web site loading, and measure performance
  15. Install Puppeteer will download a version of Google Chrome/ Chromium

    that works with the library as well as your OS. It’s a much simpler experience than trying to install Selenium.
  16. Puppeteer • You can use it as part of your

    testing strategy • It can be used inside integration services like CircleCI • You can even use it in AWS Lambda functions
  17. Puppeteer is loaded into Cucumber’s world.js file, a global context

    that all step definitions can access. The world.js file lives inside the features folder, and is loaded automatically when running Cucumber
  18. Dashku • A dashboard app • 1st version was built

    back in 2012 as a Realtime web app using a framework called SocketStream • The new version has been built as a SPA and API, with React on the frontend and Express/MongoDB/Redis on the backend. • All of the features in the app so far have been built in a Behaviour Driven Development fashion.
  19. The E2E repo needs to load the SPA and the

    API, as well as perform the setup and teardown of the app. But how do we do that?
  20. NPM • It isn’t just a package manager • You

    can use it to stitch together a couple of dependencies in order to achieve a larger goal • It can coordinate the setup and teardown of multiple components for testing via npm script commands • Let me show you the package.json for the dashku- integration repo
  21. I can then point to local copies of the web

    and api repos with npm link
  22. Now when I create a new product feature, I can

    write the tests in Cucumber, then implement the feature in the SPA, and then in the API
  23. And when I need to run the tests, I can

    coordinate the setup across the components from one place
  24. Dashku uses MongoDB & Mongoose* * but I am considering

    PostgreSQL and Objection.js instead
  25. How do I get Cucumber to directly put data into

    the database and clean it up during test runs?
  26. Inserting data • Seeding data happens as part of the

    Cucumber feature scenarios • Cucumber then loads the step definition function that matches. • The step definition code is abstracted away, for reasons that will become clearer later on. features/Login.feature features/step_definitions/common_steps.js
  27. The other benefit is that you can use Node’s Async/Await

    to combine step definitions for a single step
  28. Ideally we don’t want to repeat those 7 lines every

    time we want to login a user in a Cucumber scenario.
  29. Selecting elements in the page to click, fill in and

    check that they’re there • You can use CSS selectors to get at elements • I have a nice large list of CSS selectors that are referenced from a JS object tree. • XPath support is available as well.
  30. If you want to test across multiple browsers, do look

    at using Selenium or webdriver.io in place of Puppeteer
  31. There’s a chapter on it in my book Also in

    Mandarin Chinese! Thanks to Goddy Zhao for translating