Transcript
Page 1: Easy tests with Selenide and Easyb

Easy:) Tests with Selenide and Easyb

Iakiv Kramarenko

Page 2: Easy tests with Selenide and Easyb

Conventions :)

● Sympathy colors***:

Green =

Orange =

Red =

*** often are subjective and applied to specific context ;)

Page 3: Easy tests with Selenide and Easyb

● At project with no Web UI automation, no unit testing

● With 4(5) Manual QA

– Using checklists + long detailed End to End test cases

● With 1 QA Automation found

Page 4: Easy tests with Selenide and Easyb

Testing single page web app

● Ajax

● only <div>, <a>, <input>

– Inconsistent implementation

● No confident urls

● One current Frame/Page with content per user step

– Deep structure: ● Authorization > Menus > SubMenus > Tabs > Extra > Extra

– Modal dialogs

Page 5: Easy tests with Selenide and Easyb

Met Requirements

● Automate high level scenarios

– use AC from stories

– existed Manual Scenarios

● Use 3rd party solutions

– Java Desired

● Involve Manual QA

– provide easy to use solution

– BDD Desired

● In Tough Deadlines :)

Page 6: Easy tests with Selenide and Easyb

Dreaming of framework...● Fast in development

– Using instruments quite agile to adapt to project specifics

● Extremely easy to use and learn

● Simple DSL for tests

● BDD – light and DRY as much as possible

Page 7: Easy tests with Selenide and Easyb
Page 8: Easy tests with Selenide and Easyb

“Raw” Webdriver with tunings (HtmlElements, Matchers, etc.)

● No convenient and concise Ajax support out of the box

● Code redundancy

– Driver creation

– Finding elements

– Assert element states

● Harmcrest Matchers are easy, but assertThat() knows nothing about Ajax

– HtmlElements gives powerful but bulky “waiting” decorators (see links [1][2])

Page 9: Easy tests with Selenide and Easyb

Concordion

● Hard to extend

– Custom commands (asserts)

<html xmlns:concordion="http://www.concordion.org/2007/concordion"> <body> <p concordion:assertEquals="getGreeting()">Hello World!</p> </body></html>

Page 10: Easy tests with Selenide and Easyb

Thucydides

● No convenient Ajax support

– Asserts and Conditions are bound● Hard to extend

● Framework, not a Lib

– Not agile● It's hard to use some patterns (e.g. LoadableComponent)

● Monstrous Manual :)

Page 11: Easy tests with Selenide and Easyb

= Redundancy

Page 12: Easy tests with Selenide and Easyb

Not BDD

Page 13: Easy tests with Selenide and Easyb

Easy:) Instruments

Page 14: Easy tests with Selenide and Easyb
Page 15: Easy tests with Selenide and Easyb

@Test

public void userCanLoginByUsername() {

open("/login");

$(By.name("user.name")).setValue("johny");

$("#submit").click();

$(".loading_progress").should(disappear);

$("#username").shouldHave(text("Hello, Johny!"));

}

Page 16: Easy tests with Selenide and Easyb

Selenide Pros● Wrapper over Selenium with Concise API

● Lib, not a Framework

– You still have your raw WebDriver when needed

● should style asserts

– Independent from Conditions

– Waiting for conditions (Ajax friendly)

● Screenshot reporting on each failed should

● Screenshot API

– Providing screenshots' context

– Get all screenshots for context

● Actively supported by authors

Page 17: Easy tests with Selenide and Easyb

Killer FeatureSelenide Conditions

Page 18: Easy tests with Selenide and Easyb

public static final Condition checked = new Condition("checked") {

@Override

public boolean apply(WebElement element) {

return isChecked(element);

}

@Override

public String actualValue(WebElement element) {

return isChecked(element) ? "checked" : "unchecked";

}

@Override

public String toString(){

return "checked";

}

};

Page 19: Easy tests with Selenide and Easyb

Or even shorter

public static final Condition checked = new Condition("checked") {

@Override

public boolean apply(WebElement element) {

return isChecked(element);

}

};

Page 20: Easy tests with Selenide and Easyb

Custom Condition Examples

Page 21: Easy tests with Selenide and Easyb

Aliases

Page 22: Easy tests with Selenide and Easyb

Implementation

public static final Condition checked =

Condition.hasClass("checked");

public static final Condition enabled =

Condition.hasNotClass("disabled");

public static final Condition expanded =

Condition.attribute("area-expanded", "true");

Page 23: Easy tests with Selenide and Easyb

Usage

showPasswordCheckBox().shouldBe(not(checked));

applyButton().shouldBe(enabled);

treeItem.shouldBe(expanded);

Page 24: Easy tests with Selenide and Easyb

Usage: is

public static void ensureExpanded(SelenideElement item){

if (item.is(not(expanded))){

expand(item); }}

Page 25: Easy tests with Selenide and Easyb

Own implementation

Page 26: Easy tests with Selenide and Easyb

Implementation (1)public static final Condition inRadioMode(final String radioMode){ return new Condition("in radio mode: " + radioMode) { @Override public boolean apply(WebElement webElement) {

boolean res = true; for(WebElement mode: Mode.modes(webElement)){

if (Mode.value(mode).equals(radioMode)){ res = res &&

mode.getAttribute("class").contains("active"); } else { res = res && !

mode.getAttribute("class").contains("active"); } } return res; } };}

Page 27: Easy tests with Selenide and Easyb

Implementation (2)

public static final Condition faded = new Condition("faded with backdrop") {

@Override public boolean apply(WebElement element) {

return backDropFor(element).exists(); }};

Page 28: Easy tests with Selenide and Easyb

Implementation (3)

public static Condition leftSliderPosition(final Integer position)

{

return new Condition("left slider position " + position)

{ @Override public boolean apply(WebElement webElement) {

return

getLeftSliderCurrentPosition(webElement).equals(position); } };}

Page 29: Easy tests with Selenide and Easyb

Usage

tabContainer().shouldBe(faded);

accessRadioButtons().shouldBe(inRadioMode(PRIVATE));

scheduler.shouldHave(leftSliderPosition(100));

Page 30: Easy tests with Selenide and Easyb

Composition*

* public static final will be omitted for simplicity

Page 31: Easy tests with Selenide and Easyb

ImplementationCondition loadingDialog = condition(loadingDialog(), exist);Condition applyButtonDisabled = condition(primeBtn(), disabled);Condition cancelButtonDisabled = condition(scndBtn(), disabled);

Condition processed = with_(no(Modal.dialog()));Condition loaded = and(processed, with_(no(loadingDialog)), with_(applyButtonDisabled));

Condition savedForSure = and(loaded, with_(saveSuccessMsg()));

Condition failedToSave = and( processed, with_(no(loadingDialog)), with_(not(applyButtonDisabled)), with_(no(saveSuccessMsg())), with_(not(cancelButtonDisabled)), with_(saveErrorsMsg()));

Page 32: Easy tests with Selenide and Easyb

Usage

//fill page with valid/invalid data...

Page.save()

Page.shouldBe(and( failedToSave, with(usernameValidation(), currentPassValidation()), with(no(newPassValidation(), matchPassValidation()))))

//fix errors and save...

Page.shouldBe(savedForSure)

Page 33: Easy tests with Selenide and Easyb

Selenide Cons

● Young:)

– Many things can be improved● Error messages● Condition helpers● Screenshot API

– Tones of them have been resolved so far

– Others can be implemented as your own extensions

● Not all-powerfull

– For some things you will still need raw WebDriver

Page 34: Easy tests with Selenide and Easyb
Page 35: Easy tests with Selenide and Easyb

Easyb Pros● Gherkin (given/when/then) and its implementation live at

the same file

– better maintainability

– more DRY code

● no implementation => “pending” test

● simple but nice looking reports

● groovy as a script language for tests

– scenarios are ordered

Page 36: Easy tests with Selenide and Easyb

Easyb Cons

● bad support of framework from authors.● some features are broken

– before_each

● no tags per scenario/step– only tags per story

● Stack trace of error messages is clipped● No out of the box way to put listeners on

steps/scenarios● “Shared steps” feature is present but not quite

handy

Page 37: Easy tests with Selenide and Easyb

Easyb Selenide Integration

Page 38: Easy tests with Selenide and Easyb

Problem Selenide shoulds vs Easyb shoulds

Easyb catches any 'should' (shouldBe, shouldHave, ...) except “should” and “shouldNot”

showPasswordCheckBox().shouldNot(checked);

//Less readable:(

Page 39: Easy tests with Selenide and Easyb

Solution => Decorators

showPasswordCheckBox().shouldNot(be(checked));

showPasswordCheckBox().should(be(not(checked)));

Page 40: Easy tests with Selenide and Easyb

All Together :)

Page 41: Easy tests with Selenide and Easyb

Preconditions to BDD

● PO knows what is Criteria of Good Requirement

● Manual QA knows how to write “Automatable” Scenarios

Team is competent :)

Page 42: Easy tests with Selenide and Easyb

Pending Easyb Story by PO

description "Products List page"

scenario "Add new product", {

given "On Products List page"

then "new product can be added"

}

Page 43: Easy tests with Selenide and Easyb

Pending Detailed Easyb Story by Manual QA

description "Products List page"

scenario "Add new product", {

given "On Products List page"

and "No custom product with 'Product_1' name exist"

then "new product with 'Product_1' name can be added"

and "after relogin still present"

}

Page 44: Easy tests with Selenide and Easyb

Implemented Easyb Storydescription "ProductsList test"tags "functional"BaseTest.setup() scenario "Add new product", { given "On ProductsList page",{ ProductsList.page().get() } and "No custom product with '" + TEST_PRODUCT + "' name exist", { Table.ensureHasNo(cellByText(TEST_PRODUCT)) } then "new product with '" + TEST_PRODUCT + "' name can be added", { ProductsList.addProductForSure(TEST_PRODUCT) } and "after relogin still present", { cleanReLogin() Table.cellByText(TEST_PRODUCT).should(be(visible)); }}

Page 45: Easy tests with Selenide and Easyb

Easyb Report

Page 46: Easy tests with Selenide and Easyb

FailedEasyb Report

Page 47: Easy tests with Selenide and Easyb

Alternative: TestNG testpublic class ProductManagement extends AbstractTest {

@Test

public void testNewProductCanBeAdded() {

ProductsList.page().get();

Table.ensureHasNo(cellByText(TEST_PRODUCT));

ProductsList.addProductForSure(TEST_PRODUCT);

cleanReLogin();

Table.cellByText(TEST_PRODUCT).should(Be.visible);

}

}

Page 48: Easy tests with Selenide and Easyb

Alternative: TestNG Report

Page 49: Easy tests with Selenide and Easyb

Failed TestNG Report

Page 50: Easy tests with Selenide and Easyb

When Easyb ?

● Detailed reporting of test steps

● Ordered tests execution (as present in the file)

● “Somebody” wants Gherkin

– Automation resources are limited, and help may come from PO or Manual QA providing detailed 'steps to code'

Page 51: Easy tests with Selenide and Easyb

When TestNG/Junit ?

● When you have strong 'agile' devs/automation which know why what and how to test and do write tests.

– Hence you never need pretty looking reports to please your manager customer because you just have high quality product.

Page 52: Easy tests with Selenide and Easyb

Ideas for improvements

● Kill Kenny

– if he is the only who wants Gherkin:)

– and stay KISS with TestNG/Junit

● Contribute to Easyb:)

● Bless Selenide:)

– Authors will contribute nevertheless

Page 53: Easy tests with Selenide and Easyb
Page 54: Easy tests with Selenide and Easyb

Q&A

Page 55: Easy tests with Selenide and Easyb

Resources, Links

● Src of example test framework: https://github.com/yashaka/gribletest

● Application under test used in easyb examples: http://grible.org/download.php

● Instruments

– http://selenide.org/

– http://easyb.org/

Page 56: Easy tests with Selenide and Easyb

● To Artem Chernysh for implementation of main base part of the test framework for this presentation

– https://github.com/elaides/gribletest● To Maksym Barvinskyi for application under test

– http://grible.org/● To Andrei Solntsev, creator of Selenide, for close

collaboration on Selenide Q&A, and new features implemented:)

Page 57: Easy tests with Selenide and Easyb

Contacts

[email protected]

● skype: yashaolin

● http://www.linkedin.com/in/iakivkramarenko


Top Related