Software development
phmb@cin.ufpe.br ◈ twitter.com/pauloborba
Paulo Borba
Informatics Center
Federal University of Pernambuco
Evaluation of the Introduction to Groovy and Grails class
•
Only 10 answers!•
"Tive um péssima experiência tentando ler o cap 3 e 4. Os dois caps falam de ruby e isso se torna muito difícil”•
''O material sobre Groovy/Grails deveria ter sido passado antes da aula”•
"Bem, acho que aulas desse tipo deveriam ser práticas em laboratório"Class structure
•
Check previous activities•
Log into google with your CIn account•
Access and answer today’s questions (…)•
Discuss class material• what haven’t you understood? what don’t you agree?
what haven’t you liked? what are you missing to perform the project task?
•
Hands-on testing implementationTesting: implementation, maintenance and
execution
Directly connecting requirements
(scenarios) and tests
Feature scenarios
Scenario: new article
Given the system has no article entitled
"A theory of software product line refinement"
When I create the article "A theory of software
product line refinement" with file name "TCS.pdf"
Then the article "A theory of software product line refinement" is properly stored by the system
Via controllers, given and when
Given(~'^the system has no article
entitled "([^"]*)"$') { String title ->
article = Periodico.findByTitle(title) assert article == null
}
When(~'^I create the article "([^"]*)" with file
name "([^"]*)"$') { String title, filename ->
TestDataAndOperations.createArticle(title, filename) }
Via controllers, then
Then(~'^the article "([^"]*)" is properly stored by the system$') { String title ->
article = Periodico.findByTitle(title)
assert TestDataAndOperations.compatibleTo(
article, title) }
Auxiliary classes
static public void createArticle(String title, filename) { def cont = new PeriodicoController()
cont.params << TestData.findArticleByTitle(title) << [file: filename]
cont.request.setContent(new byte[1000]) cont.create()
cont.save()
cont.response.reset() }
GUI based scenario
Scenario: new article web
Given I am at the publications menu When I select the "Article" option
And I select the new article option Then I can fill the article details
GUI based test, given
Given(~'^I am at the publications menu$') { ->
to LoginPage at LoginPage
page.add("admin","adminadmin") at PublicationsPage
}
GUI based test, when and then
When(~'^I select the "([^"]*)" option$') { String o ->
at PublicationsPage page.select(o)
}
Then(~'^I can fill the article details$') { ->
at ArticleCreatePage
page.fillArticleDetails() }
Pages, content
class ArticleCreatePage extends Page { static url = "periodico/create"
static at = { …
title ==~ gp.msg("default.create.label",…) journal != null
}
static content = { journal { $("input", id: "journal") } }
… }
Pages, functions
class ArticleCreatePage extends Page { …
def fillArticleDetails() {
$("form").title = "A theory of …"
$("form").journal = "Theoretical Computer …"…
} }
Pages, more functions
class PublicationsPage extends Page { …
def select(String s) {
$('div', id: 'status').find('a', text: s).click() }
def getLink(String linkName) {
$('div#status a', text: linkName) }
}
Practices
•
Parametrize tests•
Each test can run independently of the others, assuming a fresh application instance•
Passing state between steps•
Before pushing (sometimes committing), make sure all tests pass•
Executed 200 tests without a single error or failurePrinciples
•
Run test with different arguments and state content•
boundary cases, focus on coverage•
Positive and negative cases•
Regression•
Balance between unity, integration and acceptance testsApplication as a state machine
•
Graph representing states and possible transitions•
Behavior desired by the user should appear as paths in this graph (traces), undesiredbehavior should not appear
•
Scenarios should verify that desired traces can be observed by testing the applicationCreate interface when little functionality is available
class PeriodicoController { create() {}
save() {}
}
functionality interface
Checklist
Test behavior should strictly conform to scenario semantics
When(~'^I select to view "([^"]*)" in resulting list$') { String title ->
at ArticlesPage
page.selectViewArticle(title) at ArticleShowPage
} first and third command are
not implied by the scenario step semantics
Avoid ambiguities due to similar step sentences
Then(~'^I can fill the article details$') {->
at ArticleCreatePage
page.fillArticleDetails() }
Then(~'^I can fill the tool details$') { ->
at FerramentaCreatePage page.fillToolDetails()
}
Do not duplicate test code
def fillLoginDataOnly(...) {
$("form").username = username $("form").password = password }
def fillLoginDataAndSubmit(...) {
$("form").username = username $("form").password = password $("form").signIn().click()
} class ResearchGroupPage extends Page {
static url = "researchGroup/list" ...
}
class ResearchGroupListPage extends Page { static url = "researchGroup/list" ...
}
Tests should clean up environment at the end
After() { ...
def uploadsFolder = new File(...) uploadsFolder.listFiles().each { innerFile ->
innerFile.deleteOnExit() }
}
Do not mix GUI and controller tests:
they simulate different application instances
Given(~'^I am at the articles page and the article "([^"]*)"
is stored in the system with file name "([^"]*)"$') { String title, filename ->
...
TestDataAndOperations.createArticle(title, filename) article = Periodico.findByTitle(title)
assert article != null to ArticlesPage
at ArticlesPage }
Tests should be plataform
(including browser) and language independent
class ArticleCreatePage extends Page { static url = "article/create"
static at = {
def gp = new GetPageTitle()
def a = gp.msg("...article.label")
def t = gp.msg("...create.label", [a]) title ==~ t
...
Testing research at CIn
•
Test generation and static analysis tools:Marcelo e Paulo
•
Model-based testing: Alexandre Mota, Juliano e Augusto•
Test selection and execution: JulianoSoftware development
phmb@cin.ufpe.br ◈ twitter.com/pauloborba
Paulo Borba
Informatics Center
Federal University of Pernambuco