1. Jak to zrobić w JavaScript
Mini warsztat automatyzacji testów
2. Podziękowania
Chciałbym na wstępie podziękować Łukaszowi Łukasikowi i Wojtkowi Łuczakowi za
inspiracje i pomoc w zmaganiach z JavaScript.
3. Wstęp
Materiał mini warsztatu zakłada, że uczestnik posiada
podstawową wiedzę o testowanie aplikacji web
podstawową wiedzę z zakresu programowania w dowolnym języku
podstawową wiedzę o css i xpath
Materiał nie ma za zadanie nauczyć programowania w JavaScript
Materiał dostarcza i opisuje wzorce, dzięki którym można stworzyć testy nie znając
dokładnie JavaScript
Repozytorium z przykładami znajduje się pod adresem
https://github.com/jacekokrojek/jak-to-zrobic-w-js
4. node.js
Środowisko pozwalające wykonywać kod JavaScript
Podstawowe komendy:
node – uruchamia kod JavaScript
• node – uruchamia interpreter
• node <plik> - uruchamia kod z pliku
npm – zarządza pakietami
• npm install [nazwa_modułu][@wersja] [- g]
• npm ls
• npm uninstall
5. Zadanie
Uruchom powłokę JavaScript, zdefiniuj poniższe zmienne i wykorzystaj polecenie
console.log() do wyświetlenia ich wartości.
var manuTitle = "Strona główna";
var pageTitle = "Agile & Automation Days " + "| Konferencja i Warsztaty";
var year = 2015;
var pageTitleWithYear = pageTitle + " " + year;
6. Zadanie
Uruchom powłokę JavaScript, zdefiniuj poniższe zmienne i wykorzystaj polecenie
console.log() do wyświetlenia ich wartości.
var menuTitle0 = "Strona główna";
var menuTitle1 = "O wydarzeniu";
var menuTitles = [menuTitle0, menuTitle1]
Czy umiesz wyświetlić każdy z elementów tablicy menuTitles osobno ?
7. Zadanie
Uruchom powłokę JavaScript, zdefiniuj poniższe zmienne i wykorzystaj polecenie
console.log() do wyświetlenia ich wartości.
var menuItem0 = { index: 0, title: "Strona główna"};
var menuItem1 = { index: 1, title: "O wydarzeniu "};
var menuItems = [ menuItem0, menuItem1 ];
Czy umiesz wyświetlić tytuł każdego z elementów tablicy osobno?
8. Protractor
Pracuje w środowisku node.js
Umożliwia testowanie zachowania aplikacji w przeglądarce
Bazujące na funkcjach Selenium Webdriver
Dostęp do funkcji WebDriver poprzez obiekt browser lub browser.driver
Rozszerza i ułatwia korzystanie funkcji WebDriver
Do uruchomienia testu wymagane są dwa elementy
Plik konfiguracyjny
Kod testu
9. Jasmine
Narzędzie organizujące testy w JavaScript
Dostarcza szablon testu
Dostarcza bogaty zestaw asercje (ang.machers) np.
expect(true).toEqual(true)
expect(true).not.toEqual(false)
10. Przykładowy test
Przykładowy kod łączący funkcje Protractor i Jasmine
describe('Agile & Automation Days homepage', function() {
it('should have Agile & Automation Days …'), function(){
var expectedTitle = "Agile & Automation Days " +"
"| Konferencja i Warsztaty";
browser.driver.get('http://aadays.pl/');
var pageTitle = browser.driver.getTitle();
expect(pageTitle).toEqual(expectedTitle);
});
11. Gulp
Narzędzie budujące i automatyzujące zadania
Konwencja code over configuration
function runSpec(confName, suiteName) {
return gulp.src([])
.pipe(protractor ( { configFile: confName, args: ['--suite', suiteName] } ) )
.on('end', function() {
console.log('Test completed.');
})
.on('error', function (e) {
throw e
});
}
13. JasmineReporter
Dla Jasmin zostało napisanych kilka modułów poprawiających sposób raportowania
wyników.
jasmine-reporters – zapisuje wyniki w formacie JUnitXML
jasmine-spec-reporter – Wyświetla wyniki wykorzystując nazwy specyfikacji oraz
testów
protractor-html-screenshot-reporter – zapisuje wyniki testów w formacie HTML
wraz z screenshot'ami tworzonymi na zakończenie testu
15. element
Funkcja element pozwala na odnajdywanie elementu na stronie
element(by.css('p.copyright'));
element(by.xpath('//h3[contains(text(),"Agenda")]'));
element(by.tagName ('a'));
Na elemencie możemy wykonywać operacje
element(by.css('p.copyright')).isPresent();
element(by.css('p.copyright')).getText();
element(by.css('p.copyright')).getInnerHtml();
element(by.css('a.btn-big')).click();
17. element.all
Funkcja element.all pozwala na odnajdywanie wielu elementów na stronie i tworzenie
z nich tablicy
element.all(by.css('div.frontpage-block-wrap > h3'));
element.all(by.css('figcaption'));
Do elementów w tablicy mamy dostęp poprzez funkcje
element.all(by.css('div.frontpage-block-wrap > h3')).first();
element.all(by.css('div.frontpage-block-wrap > h3')).last();
element.all(by.css('div.frontpage-block-wrap > h3')).get(1);
18. Zadanie
Uzupełnij kod 2 kolejnych specyfikacji
* Wykonaj zadanie korzystając z funkcji map oraz filter
19. require and export
Funkcja require wczytuje moduł JavaScript
var homePage = require("home.js"); // var homePage = require("home");
var homePage = require("data.json"); // var homePage = require("data");
Funcja export pozwala wyeksportować obiekt
module.exports = {config: {db_host:"localhost", db_port: "3303" }}
module.exports = new HomePage();
20. Page object pattern w JavaScript
W JavaScript istnieje kilka możliwości tworzenia obiektu, jedna z nich to
var HomePage = function() {
this.registerButton = element(by.css('a.btn-big'));
this.get = function() {
browser.driver.get('http://aadays.pl/');
};
this.clickRegisterButton = function() {
this.registerButton.click();
};
};
var homePage = new HomePage(); // module.exports = new HomePage();
21. Zadanie
Zmodyfikuj kod obiektu home.js o funkcję pozwalającą na sprawdzanie tekstów linków
w stopce strony. Następnie zmodyfikuj specyfikację home.spec.js tak aby sprawdzała
poprawność linków w stopce.
Zmodyfikuj specyfikacje smoke.spec.js tak aby zawierała test sprawdzający czy
użytkownik jest przeniesiony do strony 'O wydarzeniu' po naciśnięciu odpowiedniego
link'a ze stopki.
22. Importowanie modułów
Możemy tworzyć moduły nie tylko dla stron ale również dla ich powtarzających się
fragmentów a następnie importować je do wybranych stron.
var HomePage = function() {
this.footer = require('../modules/footer');
…
}
module.exports = new HomePage();
24. Dziedziczenie w JavaScript
Klasa bazowa i jej funkcje powinna być zdefiniowana jak poniżej
var Page = function () {};
Page.prototype.load = function (url) {
browser.get('http://aadays.pl/' + url);
};
Page.prototype.getTitle = function() {
return browser.driver.getTitle();
};
module.exports = Page;
25. Dziedziczenie w JavaScript
Obiekt dziedziczący powinien należy zdefiniować w następujący sposób:
var Page = require('page');
var HomePage = function() {
Page.call(this);
this.registerButton = element(by.css('a.btn-big'));
this.clickRegisterButton = function() {
this.registerButton.click();
};
};
HomePage.prototype = Object.create(Page.prototype);
HomePage.prototype.constructor = HomePage;
26. Zadanie
Bazując na pliku page.example.js stwórz obiekt paga.js, który będzie funkcją bazową
dla obiektu homePage. Dodaj do obiektu page.js moduł stopki.
Zmodyfikuj pliki event.js oraz home.js tak aby zdefiniowane w nich obiekty dziedziczyły
funkcje z obiektu page.
27. Co jeszcze
Repozytorium zawiera przykłady
Przesuwania elementów strony
Logowania
Pobierania informacji o czasie ładowania strony
Screenshot'y