IDE. Web Driver. Server. Grid. Gemini
Жигалов Сергей
 
    это инструмент для автоматизированного управления браузерами
 
    |  | Selenium IDE | 
|  | Selenium WebDriver | 
|  | Selenium Server + Selenium Grid | 
В 2004 году, Джейсон Хаггис ... ядро было реализовано на JavaScript, многие вещи было невозможно осуществить из-за ограничений безопасности браузеров ... Selenium
В 2006 году, Саймон Стюарт ... инструмент для тестирования, который бы общался с браузером используя нативные методы операционной системы и браузера ... WebDriver
В 2008 году, слияние Selenium и WebDriver ... Selenium 2 (или Selenium Webdriver)
(Integrated Development Environment, интегрированная среда разработки) — это инструмент, используемый для разработки тестовых сценариев.

 
     
    | lodash | ||
| open | /docs/4.17.4 | |
| sendKeys | css=input[type="search"] | filter | 
| click | css=.react-menu-container li:not(.hidden)>a | |
| assertLocation | https://lodash.com/docs/4.17.4#filter | |
 
    | expert-hello-test | ||
| open | /adv/expert/exam/hello | |
| click | css=.checkbox__control | |
| clickAndWait | link=Начать тестирование | |
| click | css=.radiobox__control | |
| click | //button[@type='button'] | |
| waitForText | css=div.attempt-progress__text | 9% пройдено | ... | 
| waitForText | link=Вернуться на главную Сертификации | Вернуться на главную Сертификации | 
clickdragAndDroptypesubmitsendKeys...AndWaitclickAndWaitdragAndDropAndWaittypeAndWaitsubmitAndWaitsendKeysAndWait...AndWait| Команда | Цель | Значение | 
| store | Степан | name | 
| storeElementPresent | //div/form | hasForm | 
| storeText | //h1 | title | 
| storeEval | storedVars['title'].toLowerCase() | header | 
| Команда | Цель | Значение | 
| assertValue | id=result | 15120 | 
| verifyValue | id=result | 15120 | 
| waitForValue | id=result | 15120 | 
| Команда | Цель | Значение | 
| goBackAndWait | ||
| verifyTextPresent | Добро пожаловать на мою страницу | |
| type | id=phone | (555) 666-7066 | 
| type | id=address1 | ${myVariableAddress} | 
цель, идентифицирующая элемент на странице веб-приложения
identifier=loginFormid=loginFormname=usernamelink=Начать тестированиеxpath=/html/body/form[1]//form[1]//form[@id='loginForm']/input[4]//input[@name='continue'][@type='button']dom=document.getElementById('loginForm')dom=document.forms[0]document.forms[0].elements[3]css=form#loginFormcss=input[name="username"]css=#loginForm input[type="button"] Шаблоны дают пользователю возможность описывать искомый текст с помощью специальных символов, вместо того, чтобы указывать этот текст в точности
Автоматизация рутины
Знакомство с командами Selenium
Работает только в Firefox
- Открыть http://www.google.com
- Набрать `webdriver` в строке поиска
- Кликнуть по кнопке
driver.get('http://www.google.com');
driver.findElement(webdriver.By.id('q')).sendKeys('webdriver');
driver.findElement(webdriver.By.id('btnG')).click();
        
browser
    .get("http://www.google.com")
    .elementById('q')
    .sendKeys('webdriver')
    .elementById('btnG')
    .click()
        
client
    .url('http://google.com')
    .setValue('#q','webdriver')
    .click('#btnG')
        
# Загружаем selenium-server
curl -O http://selenium-release.storage.googleapis.com/3.0/selenium-server-standalone-3.4.0.jar
# Загружаем и распаковываем geckodriver
curl -L https://github.com/mozilla/geckodriver/releases/download/v0.16.0/geckodriver-v0.16.0-macos.tar.gz | tar xz
# Запускаем selenium-server
java -jar -Dwebdriver.gecko.driver=./geckodriver selenium-server-standalone-3.4.0.jar
         
    
# Установка selenium-standalone
npm install selenium-standalone --save-dev
# Установка необходимых драйверов браузеров
./node_modules/.bin/selenium-standalone install
# Запуск сервера
./node_modules/.bin/selenium-standalone start
        
# Устанавливаем webdriverio
npm install webdriverio --save-dev
        
const webdriverio = require('webdriverio');
const options = {
    desiredCapabilities: {
        browserName: 'firefox'
    }
};
webdriverio
    .remote(options)
    .init()
    .url('http://www.google.com')
    .getTitle()
    .then(title => console.log('Title was: ' + title))
    .end();
        
# Запускаем google-script.js
node google-script.js
>  Title was: Google
        Автоматизированный запуск
Подходит только для скриптов
Promise-интерфейс
Не параллелится
Локально нет всех браузеров
./node_modules/.bin/wdio config
        
// tests/google-test.js
const assert = require('assert');
describe('Google page', () => {
    it('should have correct title', () => {
        browser.url('http://www.google.com');
        const actual = browser.getTitle();
        assert.equal(actual, 'Google');
    });
});
        
./node_modules/.bin/wdio wdio.conf.js
        
const assert = require('assert');
describe('Converter page', () => {
    it('should convert value', () => {
        browser.url(
            'https://urfu-2016-convertor.herokuapp.com/convert.html');
        browser.setValue('#value', '1.5');
        browser.setValue('#from', 'week');
        browser.setValue('#to', 'min');
        browser.click('#send');
        browser.waitForValue('#result', 2000);
        const actual = browser.getValue('#result');
        assert.equal(actual, '15120');
    });
});
        Автоматизированный запуск
Синхронный интерфейс
Параллельный запуск тестов
Локально нет всех браузеров
 
         
         
    
export SAUCE_USERNAME="your Sauce username"
export SAUCE_ACCESS_KEY="your sauce access key"
        
./node_modules/.bin/wdio config
        
// wdio.conf.js
{
    mochaOpts: {
        timeout: 30000
    }
}
        
./node_modules/.bin/wdio wdio.conf.js
        Автоматизированный запуск
Синхронный интерфейс
Параллельный запуск тестов
Все браузеры
npm install gemini --save-dev
        
module.exports = {
    rootUrl: 'https://urfu-2016-convertor.herokuapp.com',
    gridUrl: `http://${process.env.SAUCE_USERNAME}:${process.env.SAUCE_ACCESS_KEY}@ondemand.saucelabs.com:80/wd/hub`,
    browsers: {
        chrome: {
            desiredCapabilities: {
                browserName: 'chrome'
            }
        }
    }
};
        
// gemini/converter-test.js
gemini.suite('Converter', (suite) => {
    suite.setUrl('/convert.html')
        .setCaptureElements('.container')
        .capture('enabled');
});
        
// gemini/converter-test.js
gemini.suite('Converter', (suite) => {
    suite.setUrl('/convert.html')
        /* ... */
        .capture('disabled', (actions, find) => {
            const from = find('#from');
            actions.sendKeys(from, 'Invalid value');
        });
});
        
# Создаём эталонные снимки
./node_modules/.bin/gemini update
# Тестируем
./node_modules/.bin/gemini test
        
# Устанавливаем gemini-gui
npm install gemini-gui --save-dev
# Запускаем gemini-gui
./node_modules/.bin/gemini-gui
        
gemini.suite('Converter', (suite) => {
    suite.setUrl('/convert.html')
        /* ... */
        .capture('disabled', (actions, find) => {
            const from = find('#from');
            actions
                .sendKeys(from, gemini.BACK_SPACE)
                .sendKeys(from, 'Invalid value');
        });
});