EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox...

37
EFFECTIVE END TO END TESTING WITH CODECEPTJS by Michael Bodnarchuk 2018

Transcript of EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox...

Page 1: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

EFFECTIVE END TO END TESTING WITH

CODECEPTJS

by Michael Bodnarchuk

2018

Page 2: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

ABOUT ME

Michael Bodnarchuk @davertWeb developer from Kyiv, UkraineLead developer of CodeceptJSAlso author of Codeception, Robo and othersTech Consultant, CTO at SDCLabs

Page 3: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

MY EXPERIENCE

10+ years in web developmentWriting tests since 2008Languages: JavaScript, PHP, Ruby

Page 4: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

MY VISION

Tests should be simple to write and understandTests have their priority. Don't write tests for everythingTests should follow business valuesTesting should be joyful

Page 5: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

CODECEPTJS

Page 6: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

CODECEPTJS

end to end testing frameworkhelpers for popular testing backendhigh-level uni�ed APIs for all backends~15K week installations

Page 7: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

PURPOSE OF CODECEPTJS

Ideas taken from High-level BDD-style languageRun a single test over multiple backendsDon't worry about asychronity

Codeception

Page 8: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

ARCHITECTURE

WebDriverIO Protractor Nightmare Puppeteer

ElectronWebDriver API

CODECEPTJS

Selenium Server

Firefox Browser Chrome BrowserEdge Browser

DevTools Protocol

Cloud Browsers

HELPERS

Page 9: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

BACKENDS & DEPENDENCIES

WebDriverIO =>webdriverio packageSelenium ServerChromeDriver or GeckoDriver

Protractorprotractor packageChromeDriver

Puppeteerpuppeteer package

Nightmarenightmare package

Page 10: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

SAMPLE SCENARIOScenario('todomvc', (I) => {

I.amOnPage('http://todomvc.com/examples/react/');

I.waitForElement('.new-todo');

I.dontSeeElement('.todo-count');

I.fillField('What needs to be done?', 'Write a guide');

I.pressKey('Enter');

I.see('Write a guide', '.todo-list');

I.see('1 item left', '.todo-count');

I.fillField('What needs to be done?', 'Write a test');

I.pressKey('Enter');

I.see('Write a test', '.todo-list');

I.see('2 items left', '.todo-count');

I.fillField('What needs to be done?', 'Write a code');

I.pressKey('Enter');

I.see('Write a code', '.todo-list');

I.see('3 items left', '.todo-count');

});

Page 11: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)
Page 12: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

GOALS

Focus on scenario not on implementationEasy to read and writeSeparate test code from support code

Page 13: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

FEATURES

REFACTOR TESTS!Scenario('post article', async (I, loginPage) => {

const user = await I.createUser('davert');

loginPage.login(davert);

// ..

I.see('User logged in', loginPage.messageBox);

})

Page 14: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

FEATURES

TESTS CAN BE WRITTEN IN YOUR NATIVE LANGUAGE:Scenario('Efetuar login', (Eu) => {

Eu.estouNaPagina('http://minhaAplicacao.com.br');

Eu.preenchoOCampo("login", "[email protected]");

Eu.preenchoOCampo("senha", "123456");

Eu.clico("Entrar");

Eu.vejo("Seja bem vindo usuário!");

});

Page 15: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

FEATURES

USE API TO PREPARE/CLEANUP DATA FOR TESTSconst user = await I.sendGetRequest('/api/users/1');

// create a post and save its Id

const postId = await I.sendPostRequest('/api/posts', { author: user.id,

Page 16: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

BASIC CONCEPTS

Actor - object representing a person who performs a testHelper - customized actions for the actorPageObject - grouped reusable actions accross test suiteHooks:

Custom functions performed on bootstrap/terdownCustom functions handling events

Page 17: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

FILE STRUCTUREFiles Description

codecept.json global con�g

codecept.conf.js alternative con�g

output/ temporary �les created by tests

*_test.js tests

steps.d.ts TypeScript de�nitions

steps_file.js custom actor

*_helper.js custom helper

Page 18: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

END TO END TESTING

Page 19: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

HOW TO RUN BROWSERS

Window Modevia Selenium Servervia ChromeDriver, MarionetteDriverPuppeteer or Nightmare with debug: true

Headless ModePuppeteerNightmareHeadless Chrome or Firefoxvia Dockerwith Xvfb (virtual framebu�er)

Page 20: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

WHAT TO DOopen pages: I.amOnPageact: I.click, I.fillField, I.selectOption, ...assert: I.see, I.seeElement, I.dontSeewait: I.waitForElement, I.waitForText()take information from page: await I.grabTextFrom

Page 21: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

HOW TO LOCATE ELEMENTS

CSS (most common)XPath (most powerful)Button | Link TextsField Names (most stable)Field Labels (most readable)

Page 22: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

GOOD LOCATORS

Short (ideally id of element)Doesn't rely on element's positionStable to changes

Page 23: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

I.seeElement('#user'); // good

I.seeElement('div>div>ul>li>span'); // bad

I.seeElement('//*[@id="listing-23891891"]/div/div/div[1]/div/div[2]/div/

Page 24: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

WHAT TO CHECK

Text visibility on pageElements on pageURLs on page

Page 25: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

MANAGING ASYNCHONITY

Wait for elementsWait for JavaScriptSmartWait

Page 26: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

PRACTICE

Page 27: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

BOOKING.COM

Page 28: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)
Page 29: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)
Page 30: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

INSTALL CODECEPTJSnpm install codeceptjs webdriverio --save-dev

Install Selenium Server + ChromeDriver:[sudo] npm install -g selenium-standalone

selenium-standalone install

selenium-standalone start

Page 31: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

BOOTSTRAP PROJECT./node_modules/.bin/codeceptjs init

Page 32: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

FIRST TEST./node_modules/.bin/codeceptjs gt

Feature('Book');

Scenario('test something', (I) => {

I.amOnPage('/');

pause();

});

Page 33: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

I.fillField('ss', 'Kyiv')

I.click('li[data-label="Kiev, Ukraine"]');

I.fillField('checkin_monthday', "09");

I.fillField('checkin_month', '07');

I.fillField('checkin_year', '07');

Page 34: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

USE MOMENTJS TO FILL VALUESnpm i moment --save

moment = require('moment');

const checkinDate = moment().add(3, 'months');

const checkoutDate = checkinDate.add(3, 'days');

I.fillField('checkin_monthday', checkinDate.format('DD'));

I.fillField('checkin_month', checkinDate.format('MM'));

I.fillField('checkin_year', checkinDate.format('YY'));

Page 35: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

OPEN FIRST HOTEL const hotelNames = await I.grabTextFrom('.sr-hotel__name');

const hotelName = hotelNames[0];

I.say(`I want to book at ${hotelName}`);

within('//*[@id="hotellist_inner"]/div[1]', () => {

I.see(hotelName);

I.dontSee(hotelNames[1]);

I.click(hotelName);

});

I.switchToNextTab();

I.see(hotelName, 'h2');

Page 36: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

NEXT TASKS

Refactor to PageObjectsTry di�erent citiesFinish booking

Page 37: EFFECTIVE END TO END TESTING WITH...WebDriver API CODECEPTJS Selenium Server Edge Browser Firefox Browser Chrome Browser DevTools Protocol ... GOOD LOCATORS Short (ideally id of element)

QUESTIONS?Me: Michael BodnarchukProject: CodeceptJSWebsite: Twitter: @codeceptjs

codecept.io