component based unit testing adf with selenium

42
ADF and Selenium Component Based Unit Testing

Upload: richard-olrichs

Post on 29-Jan-2018

330 views

Category:

Technology


2 download

TRANSCRIPT

ADF and SeleniumComponent Based Unit Testing

About Us

Richard Olrichs

MN

www.olrichs.nl

@richardolrichs

Wilfred van der Deijl

The Future Group

www.redheap.com

@wilfreddeijl

AgendaDemo: Selenium

Plain Selenium Examples

Page Objects

Demo: ADF Selenium

ADF Selenium Tools

Demo: Testing Your Bounded Taskflows

Selenium 101 Demo

Selenium 101

public void simpleTest() {

WebDriver driver = new FirefoxDriver();

driver.get("http://google.com/?hl=en");

WebElement searchBox =

driver.findElement(name("q"));

searchBox.sendKeys("adf selenium");

searchBox.submit();

}

Selenium History

Selenium v1

● Uses JavaScript injection to emulate user interactionVery flaky with modern apps

● Used in OTN Article (don’t do that)

Selenium v2 (aka WebDriver)

● Native events to drive browser

Page Objects

Page Objects Martin Fowler: “It should provide an interface that's easy to program to and hides the underlying

widgetry in the window”Source: martinfowler.com/bliki/PageObject.html

Also advocated by Selenium team

ADF Selenium Tools

ADF Selenium Toolsgithub.com/wvanderdeijl/adf-selenium

Two JDev 12c Projects:

● SeleniumTools - Library JAR● RichClientDemoTest - Sample JUnit tests against ADF 12c component demo

ADF Selenium Demo

Basic JUnit Example@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

Basic JUnit Example@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

Page Object

Basic JUnit Example@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

ADF Component Object

Basic JUnit Example@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

Interact withADF Component

Basic JUnit Example@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

Test Assertion

Acquiring ADF Page Object@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

● How to start browser?● How to navigate to this page?

public class CalendarTest {

@ClassRule

public static WebDriverResource driver = new FirefoxDriverResource();

WebDriverResource starts (and stops) a web browser to run the tests

@ClassRule: invoke JUnit rule once per test class@Rule: invoke JUnit rule for each test method

Acquiring ADF Page ObjectSeleniumTools

Selenium

CustomCode

public class CalendarTest {

@ClassRule

public static WebDriverResource driver = new FirefoxDriverResource();

@Rule

public PageProvider<CalendarDemoPage> pages =

new PageProvider(CalendarDemoPage.class, PAGE_URL,

driver.getDriver());

PageProvider takes a WebDriver (browser) and knows how to navigate to a URL and instantiate a Page Object

@Rule triggers provider for each test so we start fresh

Acquiring ADF Page ObjectSeleniumTools

Selenium

CustomCode

Acquiring ADF Component@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

How does a Page Object locate components?

import com.redheap.selenium.component.AdfCalendar;

import com.redheap.selenium.page.Page;

public class CalendarDemoPage extends Page {

public AdfCalendar findCalendar() {

return findAdfComponent("dmoTpl:cal");

}

com.redheap.selenium.page.Page base class offers protected utility methodsfindAdfComponent uses (relative) JSF selectors

Acquiring ADF ComponentSeleniumTools

Selenium

CustomCode

Interacting with ADF Components@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

How did we implement component methods?

Interacting with ADF Componentsimport com.redheap.selenium.component.AdfComponent;

import org.openqa.selenium.WebElement;

import org.openqa.selenium.interactions.Actions;

public class AdfCalendar extends AdfComponent {

public void hoverActivityInView(int index) {

WebElement element = findAllActivitiesInView().get(index);

// move mouse to element and wait for ADF to detect hover

new Actions(getDriver()).moveToElement(element).pause(1000).perform();

waitForPpr();

}

}

Component class encapsulates interaction with HTML elementsSelenium Actions can interact with browser and mouseAdfComponent.waitForPpr waits for any PPR and complete javascript processing

SeleniumTools

Selenium

CustomCode

Interacting with ADF Components@Test

public void testHover() {

CalendarDemoPage page = pages.goHome();

AdfCalendar calendar = page.findCalendar();

calendar.hoverActivityInView(0);

assertEquals("NOTE: This popup is for demo purposes only;...",

page.findPopupNote().getValue());

}

How did we implement component methods?

import com.redheap.selenium.component.AdfComponent;

public class AdfOutputText extends AdfComponent {

public Object getValue() {

return executeScript("var cmp=AdfPage.PAGE.findComponentByAbsoluteId(arguments[0]);"

+ "return cmp.getValue()",

getClientId());

}

}

CalendarDemoPage.findPopupNote returns AdfOutputText componentComponent classes frequently use javascript to interact with componentsAdfComponent base class offers protected executeScript methodEvery component becomes a client component withoracle.adf.view.rich.automation.ENABLED=true in web.xml

Interacting with ADF ComponentsSeleniumTools

Selenium

CustomCode

Selenium Tools Component Classes● Re-use a lot of logic that would otherwise live in Page Objects● Rely heavily on ADF JavaScript API● All extend from AdfComponent

○ click(), contextClick(), doubleClick()

○ dragAndDropTo(AdfComponent target)

○ findAdfComponent(String childId)

○ isDisabled(), isDisplayed()

○ scrollIntoView()

○ and a few more

Component Class Example: AdfTablelong getRowCount()

findAdfComponent(String child, int row)

scrollToRowIndex(int row)

discloseRowDetail(int row)

List<Integer> getDisclosedRows()

selectRow(int row)

selectToRow(int row)

selectAdditionalRow(int row)

... and all AdfComponent methods

Testing Your Bounded Taskflows

Bounded Taskflow RecapJUnit Test your taskflows

Use TaskFlow Tester for isolated tests - java.net/projects/adf-task-flow-tester

PerceptualDiffMatcher - bit.ly/pdiffor look at more powerful Depicted at github.com/bslatkin/dpxdt

JaCoCo Code CoverageJUnit Rule to dump execution data - bit.ly/jacoco-ruleOptional reporter to write html report - bit.ly/jacoco-report

Browser of choice: Firefox, PhantomJS or any other...

Demo shots(reference material)

Example Test Start test in Taskflow Tester

Basic assertions

Compare screenshot

Taskflow running in Taskflow Tester

Validation Error triggered by test

JUnit Test Runner in JDeveloper

JaCoCo Code Coverage Report

JaCoCo Code Coverage shows this method wasn’t

covered in test

Not all paths tested

Screenshot Diff Assertion Violation

Tested application looks different during test compared to “known

good reference”

“Known good reference”

Actual screenshot during test

Diffs indicated