Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

JS Fest 2018. Сергей Пузанков. E2E-тестирование фронтенда c Hermione

106 views

Published on

Все мы знаем, что тесты — это хорошо. Чем выгодны e2e-тесты если на проекте пока вообще нет авто-тестов? Как быстро начать писать тесты на своем проекте и улучшать стабильность системы? Куда встроить тесты в CI процесс? Я отвечу на все эти вопросы в своем докладе, а также мы с вами рассмотрим как тестировать события и различные элементы интерфейсов в браузере

Published in: Education
  • Be the first to comment

  • Be the first to like this

JS Fest 2018. Сергей Пузанков. E2E-тестирование фронтенда c Hermione

  1. 1. END-TO-END TESTING
  2. 2. ▸Yandex ▸Luxoft, GettyImages ▸MyHeritage ▸Front-end Science SERGEY PUZANKOV puzankov@frontend-science.com @puzankovcom
  3. 3. TESTING FRONT-END
  4. 4. MANUAL TESTING
  5. 5. MERGE TO MASTER
  6. 6. DEMO
  7. 7. FIX PROCESS
  8. 8. PROJECT STATUS
  9. 9. TESTING AUTOMATION
  10. 10. QA ▸Code style ▸CSS regression
  11. 11. QA ▸Unit tests ▸Functional tests ▸Integration tests ▸End-to-End tests
  12. 12. TESTING DB UI BACK-END
  13. 13. UNIT TESTING DB UI BACK-END
  14. 14. FUNCTIONAL TESTING DB UI BACK-END UI MOCKUP SERVER
  15. 15. INTEGRATION TESTING DB UI BACK-END DB UI BACK-END
  16. 16. END TO END TESTING DB UI BACK-END
  17. 17. END-TO-END TEST FRAMEWORKS
  18. 18. JS FRAMEWORKS ▸Protractor ▸Nightwatch.js ▸TestCafe ▸Codecept.js ▸WebdriverIO + Mocha ▸Hermione
  19. 19. HERMIONE
  20. 20. HERMIONE https://github.com/gemini-testing/hermione
  21. 21. RUNS TESTS IN PARALLEL ▸If you have grid with 10 browsers You could run in 10 bowsers 10 sessions in each. So you could run 100 tests in parallel.
  22. 22. EASY TO START AND USE ▸Just 1 small config and 1 test file to start. ▸All WebriverIO methods available for use.
  23. 23. EXTENSIBLE ▸Write You own plugins. ▸Use existing.
  24. 24. RETRIES FAILED TESTS ▸Sometimes browser fails.
  25. 25. RETRIES FAILED TESTS ▸Sometimes browser fails. ▸Just because it IE.
  26. 26. RETRIES FAILED TESTS ▸Sometimes browser fails. ▸Catch browser failure and restart test.
  27. 27. EXECUTES SEPARATE TESTS ▸Easy to debug - run just failed files or tests.
  28. 28. FLEXIBLE SKIP ▸Skips tests in specific browsers.
  29. 29. FLEXIBLE TEST CONFIGURATION ▸Specify predefined devices: platform, browser, resolution. ▸Specify sets: browsers, resolution, tests files.
  30. 30. LET’S CODE!
  31. 31. INSTALL npm install -g hermione
  32. 32. INSTALL module.exports = { sets: { desktop: { files: 'tests/desktop' } }, browsers: { chromeLast: { desiredCapabilities: { browserName: 'chrome' } } } };
  33. 33. TEST const assert = require(‘chai’).assert; const pageUrl = 'https://github.com/gemini-testing/hermione'; describe('github', function() { it('should find hermione', function() { return this.browser .url(pageUrl) .getText('#readme h1') .then(function(title) { assert.equal(title, 'Hermione') }); }); });
  34. 34. FILES
  35. 35. LET’S TEST
  36. 36. RUN TESTS hermione
  37. 37. RUN TESTS
  38. 38. MOST QUICK START GUIDES
  39. 39. describe('Page loaded', function() { it('should have title', function() { return this.browser .url(url.root) .getText('.header h1') .then(function(text) { assert.equal(text, 'todos') }); }); it('should have example type title', function() { return this.browser .url(url.root) .getText('.source-links h5') .then(function(text) { assert.equal(text, ‘Vanilla JavaScript Example') }); }); }); PAGE LOADED
  40. 40. describe('New todo input', function() { it('should have input with placeholder', function() { return this.browser .url(url.root) .getAttribute('.new-todo', 'placeholder') .then(function(text) { assert.equal(text, 'What needs to be done?') }); }); }); GET ATTRIBUTE
  41. 41. describe('Add new todo', function() { beforeEach(function (done) { return this.browser .url(url.root) .localStorage('DELETE', { key: 'todos-vanillajs' }) .then(function() { done(); }) }); it('should add new todo', function() { return this.browser .url(url.root) .setValue('.new-todo', 'Clean up the room') .keys('Enter') .getText('.todo-list li:nth-child(1) .view label') .then(function(text) { assert.equal(text, 'Clean up the room') }); }); }); BEFORE EACH
  42. 42. describe('Login', function() { beforeEach(function (done) { return this.browser .url(url.root) .deleteCookie('token'}) .then(function() { done(); }) }); // … }); COOKIES
  43. 43. describe('Add new todo', function() { it('should add new todo', function() { return this.browser .url(url.root) .setValue('.new-todo', 'Clean up the room') .keys(‘Enter’) .saveScreenshot(‘./debug/client/debug.png’) .getText('.todo-list li:nth-child(1) .view label') .then(function(text) { assert.equal(text, 'Clean up the room') }); }); }); DEBUG
  44. 44. describe('Add new todo', function() { it('should add new todo', function() { return this.browser .url(url.root) .setValue(‘.new-todo', 'Clean up the room') .keys(‘Enter’) .debug() .getText('.todo-list li:nth-child(1) .view label') .then(function(text) { assert.equal(text, 'Clean up the room') }); }); }); DEBUG
  45. 45. DEBUG
  46. 46. describe('Remove items', function() { beforeEach(function (done) { return this.browser .url(url.root) .localStorage('POST', { key: 'todos-vanillajs', value: '{"todos":[]}' }) .setValue(pageObject.mainInput, 'Clean up the room') .click(pageObject.mainHeader) .setValue(pageObject.mainInput, 'Check email') .click(pageObject.mainHeader) .then(function() { done(); }) }); it('should remove item', function() { return this.browser .click(pageObject.labelOfFirstItem) .click(pageObject.destroyFirstItem) .getText(pageObject.labelOfFirstItem) .then(function(text) { assert.equal(text, 'Check email') }); }); }); PREPARE DATA
  47. 47. OTHER ACTIONS
  48. 48. ACTIONS http://webdriver.io/api.html
  49. 49. PAGE OBJECT
  50. 50. module.exports = { mainHeader: '.header h1', exampleType: '.source-links h5', mainInput: '.new-todo', labelOfFirstItem: '.todo-list li:nth-child(1) .view label', counterNumber: '.todo-count strong', destroyFirstItem: '.todo-list li:nth-child(1) .destroy' }; PAGE OBJECT describe('New todo input', function() { it('should have input with placeholder', function() { return this.browser .url(url.root) .getAttribute(pageObject.mainInput, 'placeholder') .then(function(text) { assert.equal(text, 'Pls enter task') }); }); });
  51. 51. LOCALIZATION
  52. 52. it('should add new todo', function() { return this.browser .url(url.root) .setValue(pageObject.mainInput, texts.todoLine1) .keys('Enter') .getText(pageObject.labelOfFirstItem) .then(function(text) { assert.equal(text, texts.todoLine1) }); }); L10N { "inputPlaceHolder": "What needs to be done?", "todoLine1": "Clean up the room", "todoLine2": "Check email" }
  53. 53. BROWSERS
  54. 54. BROWSERS ▸PhantomJS - RIP.
  55. 55. BROWSERS ▸Use ChromeWebDriver. https://sites.google.com/a/chromium.org/chromedriver/downloads
  56. 56. BROWSERS ▸Docker with browser.
  57. 57. BROWSERS ZOO ▸Grid.
  58. 58. CI
  59. 59. CONTINUOUS INTEGRATION DEV E2ESTA GE PRO D DEV E2E STA GE PRO D E2E DEV E2E STA GE PRO D E2EE2E
  60. 60. CI PREPARATION ▸Env setup. ▸Clear after tests. ▸Endpoints for reset data. ▸Specify suits for different envs and domains.
  61. 61. BIT.LY/E2E-LAB
  62. 62. THANK YOU FOR
  63. 63. QUESTIONS puzankov@frontend-science.com @puzankovcom

×