Escolar Documentos
Profissional Documentos
Cultura Documentos
PAGE OBJECTS
Organizando seus Testes Funcionais
!"#$%&!#'%#($#)*'"+!#'%#,%-&./
AUMENTANDO A MANUTENIBILIDADE DE TESTES FUNCIONAIS ATRAVÉS DA ORIENTAÇÃO A OBJETOS.
/ 46
Eder Ignatowicz | @ederign
Doutorando em Engenharia Elétrica na Unicamp,
é mestre em Engenharia Elétrica pela Unicamp (2009)
e formado em Ciência da Computação pela Universidade
Estadual de Londrina (2007). Atualmente é engenheiro de
Software na Dextra Sistemas e leciona diversos cursos de
graduação e pós-graduação na Faccamp e Unisal e editor do
InfoQ Brasil.
Figura 1. Representação do pattern Page Object: as páginas de busca do Google são representadas por objetos PageObject que forne-
cem métodos públicos, encapsulando os detalhes para manipulação da página e disponibilizando o acesso aos diversos testes que a
utilizam.
47 \
3/(/*:/*3$","%$(02)K/3,3)"3$"3)')*#$2#/()*5$7"
» Métodos retornam outros Page Objects: ,$")K)%:- @Test
5,+":("(.5$3$"3)":("D,>)"R;S)%5!"$"(.5$3$"0$3)" public void testaBuscaSeleniumTest() {
+)5$+*,+"$:5+$"D,>)"R;S)%57"D$+")K)(02$-",$"',2- PaginaDeBusca paginaDeBusca =
#,+":("%,3,'5+$"3)":("%2/)*5)!",5+,#.'"3$"(.5$3$" PaginaDeBusca.acessa(driver);
D,>/*,G*%2:',$H)Y2/)*5)7',2#,+Y,3,'5+$UV!" #$%&" PaginaDeResultadoDaBusca
+)%);)!" %$($" +)5$+*$!" :(," /*'5b*%/," 3)" D,>/*,- paginaDeResultadoDaBusca =
Y$*':25,H)Y2/)*5)'7" H)'5," 4$+(,!" ." 0$''1#)2" %$- paginaDeBusca.realizaBusca(
*E)%)+" $" J:K$" 3," ,02/%,=9$" ,5+,#.'" 3," /*5)+,=9$" “selenium test”);
)*5+)"$'"$;S)5$'7 Assert.assertTrue(paginaDeResultadoDaBusca
R:5+$" 0$*5$" /(0$+5,*5)" *," :5/2/?,=9$" 3$" D,>)R;- .encontrouSite(“seleniumhq.org”));
S)%5"."A:)"#$%&"0$3)")'%+)#)+"'):"%P3/>$"3)":(,"4$+(," }
(,/'" 2)>1#)27" 8" A:,/'" '9$" $'" +),/'" ;)*)41%/$'" 3)'5," 0+)-
$%:0,=9$T" ^(" %P3/>$" 2)>1#)2" ." *)%)'',+/,()*5)" :(" @Test
%P3/>$" 3)" (,*:5)*=9$" '/(02)'" U(,*:5)*1#)2V7" ^(" %P- public void testaBuscaPageObjectPattern() {
3/>$" 2)>1#)2" 5$+*,\')!" 0$+" '/" 'P!" :(," 3$%:()*5,=9$" 3$" PaginaDeBusca paginaDeBusca =
'/'5)(,7"8'5)"O25/($"0$*5$!"/*%2:'/#)!"0$3)"')+",25,()*- PaginaDeBusca.acessa(driver);
5)" 0$5)*%/,2/?,3$" %$(" ," :5/2/?,=9$" 3," %$(;/*,=9$" D,- PaginaDeResultadoDaBusca
>)R;S)%5")"HFc"UH$(,/*"F0)%/Z%"c,*>:,>)V"$:",2>:(," paginaDeResultadoDaBusca =
4)++,()*5,"3)"dHH"Ud)E,#/$+"H+/#)*"H)'/>*V"')*3$!")(" paginaDeBusca.realizaBusca
(:/5$"%)*C+/$'!"':;'5/5:5$'"3$'"(.5$3$'"5+,3/%/$*,/'"3)" (“pageobject pattern”); Assert.assertT
3$%:()*5,=9$7 rue(paginaDeResultadoDaBusca
.encontrouSite(“code.google.com/p/sele
Implementando o padrão nium/wiki/PageObjects”));
^("0$*5$"/*5)+)'',*5)","')"$;')+#,+!"*$"D,>)"R;- }
S)%5!"."A:)"')"5+,5,"3)":("0,55)+*!"$:"')S,!"*9$")'5C",5+)- @AfterClass
2,3$","*)*E:(,"/(02)()*5,=9$")'0)%1Z%,7"D,+,"/2:'5+,+" public static void %-'$!3'4/5./5() {
':," :5/2/?,=9$" *)'5)" ,+5/>$!" :5/2/?,+)($'" $" 4+,()6$+ " driver.close();
F)2)*/:("Ue7fW;V"0,+,"g,#,7"[$")*5,*5$!"sua /3)/,"."#C2/- }
3,"0,+,"A:,2A:)+"2/*>:,>)(78++$-"R+/>)("3,"+)4)+&*%/," }
*9$")*%$*5+,3,7
Y$()=,+)($'" *$''$" )K)(02$" /(02)()*5,*3$" :(" R"A:)"')+/,(")'5)'"$;S)5$'"D,>/*,H)d:'%,")"D,>/-
5)'5)" 0,+," ," ;:'%," 3$" _$$>2)7" D)*')($'!" /*/%/,2()*5)!" *,H)N)':25,3$H,d:'%,T"I*5)+/$+()*5)"4$/"#/'5$"A:)"*$"
*$"J:K$"A:)"A:)+)($'"5)'5,+-"$":':C+/$"3/>/5,+C"$"5)+- 0,55)+*"D,>)R;S)%5":(,"0C>/*,"."+)0+)')*5,3,"0$+":("
($"L')2)*/:(M"*:(,"4)++,()*5,"3)";:'%,")"3)#)+C"$;5)+" $;S)5$"D,>)"R;S)%57"H)'5,"4$+(,!"A:,/'"')+/,(",'"0C>/*,'"
%$($" 0+/()/+$" +)5$+*$" $" 2/* " 0,+," $" '/5)" 3$" F)2)*/:(7" U$;S)5$'V")*#$2#/3,'")("*$''$"5)'5)T"I"0C>/*,"3)";:'%,"
8("$:5+$"5)'5)!"')+C"4)/5,",";:'%,"0,+,"$"5)+($"L0,>)"$;- )","0C>/*,"3)"+)':25,3$!"%$++)5$T"Y$++)5$Q"<,(;.("%$-
S)%5M" )" )'0)+,($'" +)5$+*,+" ," 6/ /" %$(" %$*5)O3$" '$;+)" ()*5,($'"A:)"$'"(.5$3$'"3$'"D,>)"R;S)%5'"+)0+)')*-
)'5)",'':*5$7 5,("')+#/=$'7"F)*3$",''/(!"A:,/'"')+/,("$'"')+#/=$'"A:)"
[)'')"%$*5)K5$!"5)+1,($'":(,"%2,'')"3)"5)'5)'"3)'5," :5/2/?,+)($'"*)'',"0C>/*,T"])S,($'","c/'5,>)("e7
4$+(,- Listagem 2. Implementação dos PageObjects refe-
Listagem 1. Classe que implementa o teste a ser execu- rentes à da Página de Busca e Resultado.
tado. public class PaginaDeBusca {
private static %-'$ String URL = “http://www.google.
public class TestaMecanismoBusca { com.br”;
private static WebDriver driver; private static %-'$ long WAIT_TIME = 2000l;
private WebDriver driver;
@BeforeClass
public static void preparaTestes() { private PaginaDeBusca(WebDriver driver) {
!"#$%&"'!()$*")%!"%+",$-,.%!+/)/!.%!($*")%.%! this.driver = driver;
// browsers. Nesse caso }
!0&$1$2/)"'.%!.!-)"3.#4 public static PaginaDeBusca acessa(
driver = new FirefoxDriver(); WebDriver driver) {
} // navega para a URL desta pagina
driver.navigate().to(URL);
// retorna uma nova instancia do objeto que
// representa a pagina da busca
/ 48
/eu uso
789!*+:!"'+ '-.*5+;+<5=5#>?"'!$@&*"
Desenvolvedor de Software, com 7 anos de experiência em projetos de desenvolvimento de sistemas cor-
porativos na plataforma Java Enterprise Edition e Ruby on Rails. Formado em Ciência da Computação
na Universidade de São Paulo/São Carlos, atuando ainda como consultor de arquitetura de sistemas e
instrutor de treinamentos.
^',+"5)'5)'"4:*%/$*,/'"0,+,">,+,*5/+"+)>+)''9$")("'/'5)(,'"%$+0$+,5/#$'"
%$(02)K$'",0$*5,"0,+,":("3)',Z$"3)"$+>,*/?,=9$")"+)O'$"3)"%2,'')'"3)"5)'5)7"
8(",2>:*'"%,'$'!","/(02)()*5,=9$"3)":("O*/%$"%)*C+/$"3)"5)'5)"0$3)"3)(,*-
3,+":(")'4$+=$"(:/5$">+,*3)"3)"3)')*#$2#/()*5$!",''/("%$($"3)(,*3,+/,"(:/5$'"%2/A:)'"*,"5)2,7"^',($'","
,;$+3,>)("3)"D,>)"R;S)%5'"%$("':%)''$")(":("0+$S)5$"3$"'/'5)(,"%$+0$+,5/#$"3)":(";,*%$"3)"%b(;/$!"0)+-
(/5/*3$"A:)"*$#$'"%)*C+/$'"3)"5)'5)"4$'')("/(02)()*5,3$'"+,0/3,()*5)")",:()*5,*3$"'/>*/Z%,5/#,()*5)"
,"%$;)+5:+,"3)"5)'5)'"3$"'/'5)(,7"H/,*5)"3,'"3/#)+','",25)+*,5/#,'"A:)"SC")K0)+/()*5)/"0,+,"$+>,*/?,=9$"3)"
5)'5)'" 4:*%/$*,/'!" )'5," ()" 0,+)%)" ," ,25)+*,5/#," (,/'" /*5:/5/#," 0,+," $" :':C+/$!" 0$''/;/2/5,*3$" A:)" $" *$''$"
D+$3:%5"R6*)+!"0$+")K)(02$!"%$*'/>,"2)+")"%$(0+))*3)+"$"%P3/>$"3$'"*$''$'"5)'5)'7
49 \
/eu uso
A0=-*+B90/=+;+90=-*@'90/=>5*%5.@&*"@90
!"#$%"&$'()!(%&)*&+%,-$.&#/0"#-*&#-0#(!*1!2*3*&#/&$#-$#-&#&45*1!3*3#&3#&-%6$7*"#8&9&/#-$"#&#/&:!;)(!*&
da Computação pela Unicamp e bacharel em Ciência da Computação pela UFMG. Na Receita Federal
3%&<"*-!1.&*$5%5&)*&65)=>%&3#&?#"#)$#&3#&$#-$#-&3#&5/*-!0#&!)3#0#)3#)$#&3#&@#"!,(*=>%&#&@*1!3*=>%&
(V&V). Participa ativamente do curso de especialização em Engenharia de Software da Unicamp desde
ABBC.&#-0#(!,(*/#)$#&)*-&3!-(!01!)*-&3#&@D@&#&E*)5$#)=>%8&E!)!-$"*&0*1#-$"*-&#&$"#!)*/#)$%-&-%F"#&
temas relacionados a testes e qualidade de software em instituições e eventos, e possui uma série de
publicações nacionais e internacionais relacionadas.
gC":5/2/?,($'"EC",2>:*'",*$'"$"0,3+9$"D,>)R;S)%5"*,"F$Z'57"R"0,3+9$".")K-
5+)(,()*5)"0$3)+$'$!"5$+*,*3$","(,*:5)*/;/2/3,3)"3$'"5)'5)'":(,",5/#/3,3)"
'/(02)'")!"*,"(,/$+/,"3$'"%,'$'!"3/#)+5/3,")"0+,?)+$',7"]$%&"0$+",%,'$"SC"/(,>/*$:"%$++/>/+"(,/'"3)"W7Xff"
%,'$'"3)"5)'5)",:5$(,5/?,3$'")4)5:,*3$","/*%2:'9$"3)"5+&'"2/*E,'")(":(,"%2,'')T"
Y)+5,()*5)",A:/")'5$:"%$()*5,*3$"'$;+)"$'",'0)%5$'"L3/#)+5/3$'")"0+,?)+$'$'M7"I">)'59$"3,'"(:3,*=,'"
*$'"#C+/$'"%$(0$*)*5)'"3,'"5)2,'"%E)>,","')+"5+/#/,2!"3)'3)"A:)"$":':C+/$"5)*E,"%:/3,3$"*$"($()*5$"3)"
)'5+:5:+,+"'):'"%$(0$*)*5)'7"_$'5,+/,"3)"%$(0,+5/2E,+",2>:*'"3,3$'"/*5)+)'',*5)'"%$("$'"2)/5$+)'7"8(":("
3$'"0+$S)5$'"*$"A:,2",02/%,($'")'5)"3)'/>*"0,55)+*!"$'"+)':25,3$'"$4)+)%)+,(",$"%2/)*5)"0)2$"()*$'"hfi"3)"
)%$*$(/,"3)#/3$"a",3$=9$"3$"0,3+9$7"8("$:5+$"0+$S)5$!"$*3)"SC"E,#/,"(,/'"3)"hff"%,'$'"3)"5)'5)'",:5$(,-
5/?,3$'"%$("$"F)2)*/:(!"0+$0$+%/$*,($'"+)3:=9$"(.3/,"3)"jfi"*$")'4$+=$"0,+,"(,*:5)*=9$"3$'"5)'5)'7"
[)'5)"%,'$!"3)#$"%$()*5,+"A:)"$"'$456,+)")("A:)'59$"'$4+/,",25)+,=`)'"A:,')"A:)"3/C+/,'")("':,'"5)2,'")"
%$(0$*)*5)'7"8'5)".":("3$'"0,3+`)'"A:)"+)%$()*3$","A:,2A:)+"0)''$,"A:)"0)*')")(",3/%/$*,+",:5$(,5/-
?,=9$"3)"5)'5)'"4:*%/$*,/'"a"':,"L%,/K,"3)"4)++,()*5,'M7
/ 50
public abstract String getURL();
}
//--------------- /para saber mais
public class PaginaDeBusca extends PaginaBase {
51 \
Listagem 6. !"#$%&'"!()*%&'#+)!("*(,-+%&. itemEncontrado.getText().replaceAll(“ “, “”);
elementoEncontrado =
public class PaginaDeBusca extends PaginaBase { linkDoElementoEncontrado.contains(
private static !"# String INPUT_BUSCA =
“input#sb_form_q”; urlSiteProcurado);
private static !"# String BOTAO_DE_BUSCA =
“input#sb_form_go”;
!5$)5$!"#$!6/;@/'()!1'-.$'$+5/7(!%0(#!1+5/05(*!
public PaginaDeBusca(WebDriver driver) { $,/5/'$+5$!0('(!2(1!$)0315(!(3191+/.'$+5$=!M(!$+5/+5(*!
super(driver); '#7/'()*!-(3!0('-.$5(*!(!'$0/+1)'(!7$!4#)0/!#51.1&/-
} 7(=!N!0./3(!"#$!#51.1&/'()!#'!$,$'-.(!4/)5/+5$!)1'-.$)!
-/3/!1.#)53/3!(!#)(!$!()!9/+6()!7(!8/9$ 4G$05=!8(7$3@/-
public static PaginaDeBusca acessa(WebDriver driver) '()!#51.1&/3!$))$!5$)5$*!-(3!$,$'-.(*!-/3/!3$/.1&/3!#'/!
{ -$"#$+/!-3(;/!7$!0(+0$15(!(#!#'/!43$;$!/+<.1)$!7$!1'-
PaginaDeBusca paginaDeBusca = -/05(! +/! 53(0/! 7(! '$0/+1)'(! H((9.$! -$.(! '$0/+1)'(!
new PaginaDeBusca(driver); :1+9=
paginaDeBusca.acessaPagina(); 8(3B'*!$,53/-(.$'()!#'!-(#0(!$))$!$,$'-.(*!53/-
return paginaDeBusca; &$+7(O(!-/3/!/!3$/.17/7$!7$!)(25D/3$=!P'/91+$!"#$!;(0K!
} 5$+6/! QR! 0$+<31()! 7$! 5$)5$)! $+01'/! 7$! #'/! 2#+01(+/-
.17/7$! 0('-.$,/! $! 1'/91+$! 5/'4B'! "#$*! $'! #'! -/))(!
0('#'!/!5(7()!$)5$)!0$+<31()*!2(1!+$0$))<31(!/.5$3/3!#'!
3$"#1)15(L! 1+0.#13! #'! 0/'-(! (#! /.5$3/3! #'! 0/'-(=! F$-
public PaginaDeResultadoDaBusca
)$)-$3(IS!MT(S!F$;17(!/(!$+0/-)#./'$+5(!$!4/1,(!/0(-
realizaBusca(String conteudoDaBusca) {
-./'$+5(*!4/)5/31/!;(0K!/7$"#/3!(!8/9$ 4G$05!+(!"#/.!(!
this.preencheInputText(INPUT_BUSCA,
-/))(!2(1!'(71%0/7(=
conteudoDaBusca);
P'/91+$*! 5/'4B'*! "#$! ;(0K! -3$01)/*! $'! #'! 7$5$3-
this.clica(BOTAO_DE_BUSCA);
'1+/7(! 0$+<31(*! 0('(! -3$0(+71UT(! -/3/! )#/! $,$0#UT(*!
return new PaginaDeResultadoDaBusca(driver);
$,$0#5/3! #'! -/))(! "#$! ;(0K! G<! 5$'! 1'-.$'$+5/7(! $'!
}
(#53(! 5$)5$=! V(0K! 0(+)$9#13<*! '#15(! 2/01.'$+5$*! 06/-
'/+7(! (W)X! 8/9$ 4G$05W)X! $+;(.;17()! +/! )#/! -3$0(+71-
@Override
UT(!-/3/!)$3$'!$,$0#5/7()!$*!/))1'*!;(0K!0(+)$9#13!7$-
public String getURL() {
)$+;(.;$3!)$#!0$+<31(!7$!5$)5$)=
return “http://www.bing.com.br”;
}
} *+!($,'-"./'(0 !"$(0
//--------------- Y$)5$)!/#5('/51&/7()!)T(!#'/!$,0$.$+5$!2$33/'$+-
public class PaginaDeResultadoDaBusca extends 5/!-/3/!(!7$)$+;(.;1'$+5(!7$!)(25D/3$=!>('!5$)5$)!/#-
PaginaBase { 5('/51&/7()!9/3/+51'()!"#/.17/7$!1+5$3+/!$!$,5$3+/!7(!
private static !"# String LISTA_DE_RESULTADO = )(25D/3$=!A53/;B)!7$!5$)5$)!/#5('/51&/7()!0(+)$9#1'()!
“div#results li cite”; )$9#3/+U/! $! 0(+2(35(! -/3/! $;(.#13! 0(+)5/+5$'$+5$! #'!
)(25D/3$L!)$G/!+/!0(33$UT(!7$!4#9)*!+/!/.5$3/UT(!7$!3$-
public PaginaDeResultadoDaBusca(WebDriver driver) "#1)15()!(#!+/!3$$)53#5#3/UT(!7$!0?719(=
{ M(!$+5/+5(*!/!$)53#5#3/!7$!5$)5$)!7$)$+;(.;17/!$'!
super(driver); #'!-3(G$5(!-3$01)/!)$3!2$15/!7$!'(7(!"#$!)$G/!-())@;$.!
} '/+5$3!$!#)#23#13!7$!5/.!$)53#5#3/!$!+T(!/-$+/)!0/33$9<-
O./!0('(!#'!2/37(L!ZJ!/9(3/I!83$01)/'()!'$,$3!+()!5$)-
public boolean encontrouSite(String urlSiteProcurado) 5$)=[! (#!ZMT(! ;/'()! 2/&$3! 1))(! -(3"#$! ;/1! "#$43/3! #'!
{ '(+5$!7$!5$)5$)S!F$1,/!/))1'!0('(!$)5<L!+T(!$)5<!4('*!
List<WebElement> itensEncontrados = '/)!3$)(.;$=[!(#!(!-1(3!0$+<31(!ZV/'()!7$1,/3!()!5$)5$)!
"#$43/+7(!-(3!$+"#/+5([=
this.buscaPorElementos(LISTA_DE_ 8/9$ 4G$05!)#39$!0('(!#'!-/55$3+!"#$!;$'!/G#7/3!
RESULTADO); /! 3$)(.;$3! $)5/)! "#$)5\$)! $'! 5$)5$)! 2#+01(+/1)! "#$! )1-
boolean elementoEncontrado = false; '#./'!/!1+5$3/UT(!7$!#)#<31()!0('!(!)1)5$'/=!>(+5#7(!
for (WebElement itemEncontrado : 8/9$ 4G$05!3$-3$)$+5/!/-$+/)!#'/!7/)!1+]'$3/)!2$33/-
itensEncontrados) { // obtem o conteudo '$+5/)*!$)53/5B91/)!$!-/73\$)!-/3/!/#'$+5/3!/!"#/.17/-
de um elemento cite 7$!7(!)$#!7$)$+;(.;1'$+5(=
// dentro de cada itemencontrado
String linkDoElementoEncontrado =
/ 52