good practices on test automation
TRANSCRIPT
Good practices on test automation
Gustavo Labbate Godoy
Where are test automation on agile environments?
Several agile methodologies:
Scrum, Extreme Programming (XP), Lean Development, Feature-Driven Development (FDD), Kanban, RUP and OpenUP.
Software Development by interactive and incremental way.
TDD, Data-Driven Testing, Regression Testing.
Automation is one of the three pilars of agile methodology.
Delivery on time, with all tested and approved.
“Working software is the primary measure of progress.” (http://agilemanifesto.org)
Junit is unit test ?
What is unit test andwhat is Junit ?
Unit test
Test the smaller of the components in a isolated way.
Test methods must be independent.
Functional test
Test the behavior of the sistem, from data inputs, processing and data outputs.
assertEquals( ExpectedResult, returnProcessedData(entryData) );assertEquals( ExpectedResult, returnProcessedData(entryData) );
returnedObject = insertData(entryData);
assertNotNull(returnedObject); //Validating if insert was sucessfull
consultedObject = consultData(returnedObject);
assertEquals( consultedObject, expectedObject ); //Validating if insert was sucessfull through system query
returnedObject = insertData(entryData);
assertNotNull(returnedObject); //Validating if insert was sucessfull
consultedObject = consultData(returnedObject);
assertEquals( consultedObject, expectedObject ); //Validating if insert was sucessfull through system query
Correctly specify your tests
Correctly specify your tests
Don't say test, be more specific ...
TestCalculate - testCalc1 = shouldSumTwoInt
- testCalc2 = shouldSubtractFromSum
Test all functionality inside your method (avoid alphabetical ordering).
expectedObjects = testParameters;
expectedObjects = includeData(entryData);
assertNotNull(returnedObject); //Validating if insert was sucessfull
consultedObject = consultData(returnedObject);
assertEquals( consultedObject, expectedObject ); //Validating if insert was sucessfull through system query
expectedObjects = testParameters;
expectedObjects = includeData(entryData);
assertNotNull(returnedObject); //Validating if insert was sucessfull
consultedObject = consultData(returnedObject);
assertEquals( consultedObject, expectedObject ); //Validating if insert was sucessfull through system query
Correctly specify your tests
But ...
@Testpublic void shouldSucessfulyInclude() { … }
@Testpublic void shouldSucessfullyConsultAfterInclude() { … }
@Testpublic void shouldSucessfulyInclude() { … }
@Testpublic void shouldSucessfullyConsultAfterInclude() { … }
@FixMethodOrder(MethodSorters.NAME_ASCENDING)@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Testpublic void aShouldSucessfulyInclude() { … }
@Testpublic void bShouldSucessfullyConsultAfterInclude() { … }
@Testpublic void aShouldSucessfulyInclude() { … }
@Testpublic void bShouldSucessfullyConsultAfterInclude() { … }
Alphabetically ordering methods:
Every test method must be independent.
Execution order is random.
Parameterize test data
Read from a spreadsheet (or another external file … )
@RunWith(Parameterized.class)public Class UserInsert
@Parameterspublic static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {{"ParameterA"}, {"ParameterB"}} );}
public UserInsert(String[ ] parameters) { /* Add parameters to variables ... */ }
@RunWith(Parameterized.class)public Class UserInsert
@Parameterspublic static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {{"ParameterA"}, {"ParameterB"}} );}
public UserInsert(String[ ] parameters) { /* Add parameters to variables ... */ }
https://bitbucket.org/wakaleo/jxlunit/src/6eb465c848c8/src/main/java/com/wakaleo/training/jxlunit/SpreadsheetData.java
@Parameterspublic static Collection spreadSheetData() throws IOException {
InputStream spreadSheet = new FileInputStream(“mySheet.xls”);return new SpreadSheetData(spreadSheet).getData();
}
@Parameterspublic static Collection spreadSheetData() throws IOException {
InputStream spreadSheet = new FileInputStream(“mySheet.xls”);return new SpreadSheetData(spreadSheet).getData();
}
Selenium
Selenium IDE or Core ?
IDE
• Record & Playback
• Export to several languages (C#, Java, Perl, PHP, Python, Ruby).
• In browser test execution.
• Code refactoring: Re-record your tests...
• To avoid: use plugins (do a little programming … )
• Record only on firefox, but run on others (the script, not in IDE … )
• Don't need advanced knowledge on exported code.
Core (coding)
• API to several languages (C#, Java, Perl, PHP, Python, Ruby).
• Build your own test framework, extending selenium.
• Test execution on several browser.
• Code refactoring: update only affected test code (Page Object Model)
• Knowledge of choosen language is essential.
Promote maintainability
Promote maintainability
Use fixtures
WebDriver driver
@BeforeClass public static void runBeforeClass() throws Exception { driver = new FirefoxDriver(); selenium = new WebDriverBackedSelenium(driver, url);
capability = DesiredCapabilities.firefox(); capability.setBrowserName("firefox"); capability.setCapability(CapabilityType.TAKES_SCREENSHOT, true);}
@After public void runAfterEachTest() {
printScreen();}
@AfterClass public static void runAfterClass() {
driver.quit();}
WebDriver driver
@BeforeClass public static void runBeforeClass() throws Exception { driver = new FirefoxDriver(); selenium = new WebDriverBackedSelenium(driver, url);
capability = DesiredCapabilities.firefox(); capability.setBrowserName("firefox"); capability.setCapability(CapabilityType.TAKES_SCREENSHOT, true);}
@After public void runAfterEachTest() {
printScreen();}
@AfterClass public static void runAfterClass() {
driver.quit();}
Promote maintainability
PageObjectsObject that represents a web system screen.
public Class LoginPO
@FindBy(id="user") WebElement user; @FindBy(id="password") WebElement password; @FindBy(id="btnClose") WebElement closeButton; @FindBy(id="btnLogin") WebElement loginButton; String userAcessApp = "automation"; String passwordAcessApp = "selenium"; public void typeAndEnter(String user, String pass) { usuer.sendKeys(user); password.sendKeys(pass); loginButton.click(); }
public Class LoginPO
@FindBy(id="user") WebElement user; @FindBy(id="password") WebElement password; @FindBy(id="btnClose") WebElement closeButton; @FindBy(id="btnLogin") WebElement loginButton; String userAcessApp = "automation"; String passwordAcessApp = "selenium"; public void typeAndEnter(String user, String pass) { usuer.sendKeys(user); password.sendKeys(pass); loginButton.click(); }
Organize …
Organize ...
Using Junit Test Suite
@RunWith(Suite.class)@SuiteClasses({
TestClass1.class,TestClass2.class,TestClass3.class
})public class AllMyTests{
}
@RunWith(Suite.class)@SuiteClasses({
TestClass1.class,TestClass2.class,TestClass3.class
})public class AllMyTests{
}
Solid foundations ...
Solid foundations ...
Guarantees data integrity
Spring's configuration:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${hibernate.connection.driver_class}" /> <property name="url" value="${hibernate.connection.url}" /> <property name="username" value="${hibernate.connection.username}" /> <property name="password" value="${hibernate.connection.password}" /></bean>
Spring's configuration:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${hibernate.connection.driver_class}" /> <property name="url" value="${hibernate.connection.url}" /> <property name="username" value="${hibernate.connection.username}" /> <property name="password" value="${hibernate.connection.password}" /></bean>
DBUnit's dataSet to setup and prepare a data base
<dataset><schema.USER LOGIN="User" PASSWORD="781b4ea1d8" NAME="Test User"PASSWORD_EXPIRATION_DATE="2013-03-01 00:00:00.0" LOGIN_COUNT="0" EMAIL="[email protected]" />
</dataset>
DBUnit's dataSet to setup and prepare a data base
<dataset><schema.USER LOGIN="User" PASSWORD="781b4ea1d8" NAME="Test User"PASSWORD_EXPIRATION_DATE="2013-03-01 00:00:00.0" LOGIN_COUNT="0" EMAIL="[email protected]" />
</dataset>
Orchestrate ...
Orchestrate ...
Manage automated executions
Orchestrate ...
Manage test execution results
References
Arquillian
http://arquillian.org/
Junit
http://junit.sourceforge.net/
Selenium
http://seleniumhq.org/
DBUnit
www.dbunit.org/
Page Objects
https://docs.jboss.org/author/display/ARQGRA2/Page+Objects
http://code.google.com/p/selenium/wiki/PageObjects
Jenkins
http://jenkins-ci.org/
TestLink
http://www.teamst.org/