среда, 12 декабря 2012 г.

Основы rspec



Как проверить равенство

a.should equal(b) # Для обоих if a.equal? b
a.should be(b) #
a.should eql(b) # passes if a.eql? b
a.should == b # Для обоих if a == b
a.should eq(b) #
аналогично неравенство a.should_not == b
Пример: 

String.should == "this is a string"
[1, 2, 3].should == [1, 2, 3]

Как проверить включение или соотношение

37.should be < 100
37.should be >= 2
"This is a string".should include "str"
# Два одинаковых выражения:
"This is a string".should =~ /^This/
"This is a string".should match(/^This/)

Как проверить истинность выражения

obj.should be_true # Проходит если obj - truе (не nil и не false)
obj.should be_false # Проходит если obj - false (nil или false)
obj.should be_nil # Проходит если obj - nil
obj.should be # Проходит если obj не nil


Как проверить cуществование элемента


[].should be_empty
[].should_not be_empty
test_result.should exist
test_result.should_not exist

Как завершить тест с ошибкой или просто вывести пользовательскую ошибку

expect { 4/2 }.to_not raise_error
expect { 4/0 }.to raise_error
expect { 4/0 }.to raise_error(ZeroDivisionError)
expect { 4/0 }.to raise_error(ZeroDivisionError, "divided by 0")
o.should raise_error 

it "includes 3" do
[1, 2, 3].should include(3), "Oh noes! No three!"
end

Как проверить количество элементов

[1, 2, 3].should have(3).items
[1, 2, 3].should have_exactly(3).items
[1, 2, 3].should have_at_least(2).items
[1, 2, 3].should have_at_most(4).items
[].should be_empty


Подробнее тут и тут

вторник, 11 декабря 2012 г.

CI

AS IS

По каждому пушу происходит деплой сервера (абстрактного) и запускается билд
Если билд еще не прошел то новый не запускается.

TO BE

Вопрос - какую схему выбрать:
1. тестировать проект на тестовом сервере
тогда после каждого пуша будет происходить деплой тествого - не очень удобно.
 2. тестировать на нашем сервере селениум - для этого надо там поднять проект. И аналогично запускать деплой по каждому пушу. (Нашему или программистов?? Скорее второе) Опять же в этом случае приходим к тому, что на тестовом и на сервере селениума будут разные сборки проекта, что не очень здорово

понедельник, 10 декабря 2012 г.

Скриншоты RubySelenium

@driver.save_screenshot("./screen.png")
Такой простой командой мы сохраняем скриншот.
Сохраняется скриншот всей страницы.

Бонус - можно менять размеры окна
@driver.execute_script %Q{window.resizeTo(#{width}, #{height});

ToDo:
1. Складывать скриншоты отдельно от репозитория
2. Генерить имя скриншота в формате дата+текущее временя
3. Периодически чистить папки со скриншотами (лучше бы  по крону)
4. Написать аналогичный faq по видео

пятница, 7 декабря 2012 г.

Думки

Мне кажется я никогда не дойду до логического конца в поисках идеального шаблона для наших автотестов...

Изначально я долго долго выбирала что же взять за основу - rspec, cucumber, capybara и тд - пришла к выводу что одного rspeca более чем хватит

Дальше Николай Алименков со своим докладом подтолкнул меня к мысли разделять логику данные и реализации. Активно занялась этим вопросом. Rspec это вполне позволяет делать.

Далее я начала копать в сторону локаторов - поняла что надо юзать page-object. Так же узнала про такие вещи как Page Factory, Element Object

Ну и из последних полезных вещей я наткнулась на генераторы случайных данных - такие как Выдумщик, Рыба, Ffaker - очень классная штука кстати.

Еще в обязательном порядке хочу использовать логирование, протоколирование, обработку ошибок... Пока с этим как то тяжко...

вторник, 4 декабря 2012 г.

Особенности selenium


Элементы теста:
  1. Приложение - драйвер
  2. Тестовая логика (описание)
    -предусловия
    -сценарии
    -постусловия
  3. Технические детали (код)
  4. Тестовые данные

Основные принципы:
  1. Повторное использование кода
  2. Атомарные тесты
  3. DSL - разбиение на тестовую логику и технические детали (логика не зависит ни от переменных, ни от реализации)
  4. Справочник доменных понятий
Локаторы:

В отличае от сахи нет разделения на веб-элементы (span,textarea и тд)

Selenium предлагает семь встроенных способов поиска элементов:

Простые локаторы
  • по идентификатору элемента (значению атрибута id)
  • element = driver.find_element(:id, 'some-frame')
  • по имени элемента (значению атрибута name)
  • element = driver.find_element(:name, 'q')
  • по классу элемента(значению атрибута class)
  • element = driver.find_element(:class, 'news') (или по class_name)
    element = driver.find_element(:class_name, 'news') 
  • по тексту ссылки
  • element = driver.find_element(:link, "Зарегистрироваться") (или по link_text)
    element = driver.find_element(:link_text, "Зарегистрироваться")
    element = driver.find_element(:partial_link_text, "Регистрация") (ищется вхождение в текст ссылки)
  • по названию тега элемента
  •  element = driver.find_element(:tag_name, 'td') 
Сложные локаторы
  • по запросу XPath
  • element = driver.find_element(:xpath, "//div[@id='content']/*/span")
    element = driver.find_element(:xpath, "/html/body/div") - ищем от корня
    element = driver.find_element(:xpath, "//input") - ищем по всем вложениям элемент input
    element = driver.find_element(:xpath, "//*[@id=menu]") - ищем любой элемент с id menu
    element = driver.find_element(:xpath, "//menu")
    element = driver.find_element(:xpath, "//span[@class=test and @name=span]") и 
  • element = driver.find_element(:xpath, "//span [@class=test][@name=span]") или
  • element = driver.find_element(:xpath, "//a[text()='some text']")
    element = driver.find_element(:xpath, "//div[1]") или
    element = driver.find_element(:xpath, "//div[position()=1]")
    element = driver.find_element(:xpath, "//div[@id='test' and contains()='text']")
    element = driver.find_element(:xpath, "//div[@id='it']/*/a[counts()=1]")
    element = driver.find_element(:xpath, "/descendant::div[@id='my']/descendant::a[1]")
    Ищем среди потомков документы див my, а среди его потомков первую ссылку
    element = driver.find_element(:xpath, "//a[ancestor::div[@id='my']]")
    Ищем ссылку с родителем div (c id my)
  • element = driver.find_element(:xpath, "//*[contains(text(),'ABC')]")
  • по селектору CSS
  • обращаемся к элементам
  • element = driver.find_element(:css, "span.toolbar-link") по классу
    element = driver.find_element(:css, "span#news_class") по id
    element = driver.find_element(:css, "p") по тегу - находим все элементы p
    element = driver.find_element(:css, "*") все элементы на странице
  • обращается по атрибутам
  • element = driver.find_element(:css, "div[class=toolbar_menu]") полное совпадение
    element = driver.find_element(:css, "div[class^=toolbar]") начинается с
    element = driver.find_element(:css, "div[class$=menu]") оканчивается на
    element = driver.find_element(:css, "div[class]") div у которого есть атрибут class
    element = driver.find_element(:css, "div[class*=bar]") содержит текст
  • отношения элементов друг к другу
  • element = driver.find_element(:css, "div a") ищем все ссылки в дивах (все потомки в любой вложенности)
    element = driver.find_element(:css, "div > a") ищем ссылки в дивах (непосредственный потомки - между ними не должно быть других элементов)
    element = driver.find_element(:css, "div + div") ищем элемент сразу за элементом (между ними не должно быть других элементов)
    element = driver.find_element(:css, "div ~ div") ищем элемент за элементом (между ними могут быть другие элементы)
    element = driver.find_element(:css, "div:contains('text')") div содержит текст
    element = driver.find_element(:css, "div#menu a:nth-of-type(1)") Первая ссылка в диве с id menu
    element = driver.find_element(:css, "span[name=hello][background=green]") Ищем элемент  с 2 атрибутами
Метод, начинающийся со слов findElement находит первый элемент, удовлетворяющий условиям поиска, а метод, начинающийся с findElements – все подходящие элементы

Подробнее про локаторы для руби тут
Отличный вебинар по локаторам от Михаила Поляруша - ссылка
Подробнее про локаторы вцелом тут и тут
Про то как правильно подбирать локаторы - подробнее

Команды