-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path16_selenium_WebDriver.html
904 lines (903 loc) · 63 KB
/
16_selenium_WebDriver.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="OpenOffice.org 3.2 (Unix)">
<META NAME="CREATED" CONTENT="0;0">
<META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa">
<META NAME="CHANGED" CONTENT="20111103;15421400">
<META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa">
<META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa">
<META NAME="SDFOOTNOTE" CONTENT=";;;;P">
<STYLE TYPE="text/css">
<!--
@page { margin: 2cm }
P { margin-bottom: 0.21cm; color: #000000; font-family: "Times New Roman", serif; font-size: 12pt; font-style: normal; font-weight: normal; line-height: 100%; text-align: left; widows: 2; orphans: 2; text-decoration: none; page-break-before: auto; page-break-after: auto }
PRE { color: #000000 }
PRE.cjk { font-family: "DejaVu Sans", monospace }
-->
</STYLE>
</HEAD>
<BODY LANG="pt-BR" TEXT="#000000" DIR="LTR">
<P ALIGN=LEFT STYLE="margin-bottom: 0cm; line-height: 100%; widows: 2; orphans: 2; page-break-before: auto; page-break-after: auto">
<BR>
</P>
<P ALIGN=LEFT STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; line-height: 100%; widows: 2; orphans: 2; text-decoration: none">
<SPAN STYLE="background: transparent"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="Weslleymberg Lisboa"><META NAME="CHANGEDBY" CONTENT="weslleymberg "><META NAME="CHANGEDBY" CONTENT="weslleymberg "><META NAME="CHANGEDBY" CONTENT="weslleymberg "><META NAME="CHANGEDBY" CONTENT="weslleymberg "><FONT FACE="Times New Roman"><FONT SIZE=3>Tradução
CAP 16 <BR><BR>Capítulo 16 - Selenium WebDriver <BR><BR>Simon
Stewart <BR><BR>Selenium é uma ferramenta para automação de
navegadores, comumente usada para escrever testes de aplicações web
de ponta-a-ponta. Uma ferramenta de automação de navegadores faz o
exatamente o que você esperaria: automatiza o controle de um
navegador, sendo assim, tarefas repetitivas podem ser automatizadas.
Isto parece um simples problema a ser resolvido, mas como veremos,
muitas coisas têm que acontecer debaixo dos panos para que tudo
funcione. <BR><BR>Antes de descrever a arquitetura do Selenium é
necessário entender como as várias partes do projeto se encaixam.
<U>Por cima</U>, Selenium é uma coleção de três ferramentas. A
primeira destas, Selenium IDE, é uma extensão para Firefox que
permite aos usuários gravar e refazer testes. O paradigma
gravar/refazer pode ser limitado e não adaptável para muitos
usuários, então a segunda ferramenta da coleção, Selenium
WebDriver, provê APIs em várias linguagens para permitir um maior
controle e aplicação de praticas de desenvolvimento de software
padrão. A última ferramenta, Selenium Grid, torna possível o uso
das APIs do Selenium para controlar instâncias de navegadores
distribuídas sobre um rede de máquinas, permitindo executar mais
testes paralelamente. No interior do projeto, eles são referenciados
como "IDE", "WebDriver" e "Grid". Este
capítulo explora a arquitetura do Selenium WebDriver. <BR><BR>Este
capítulo foi escrito durante os betas do Selenium 2.0 no final de
2010. Se você está lendo o livro após o fim de 2010, então as
coisas já terão avançado, e você será capaz de ver como as
escolhas arquiteturais descritas aqui se desdobraram. Se você está
lendo antes do fim de 2010: Parabéns! Você tem uma máquina do
tempo. Pode me dar os números vencedores da loteria? <BR><BR>16.1.
História <BR><BR>Jason Huggins começou o projeto Selenium em 2004
enquanto trabalhava no ThoughtWorks do sistema feito por eles, Time
and Expenses (T&E), que fez amplo uso de Javascript. Embora o
Internet Explorer fosse o navegador dominante na época, ThoughtWorks
usou vários navegadores alternativos (em particular, as variações
do Mozzila) e enviava um relatório de erro quando o aplicativo T&E
não funcionava no navegador escolhido. Ferramentas de testes naquela
época, ou eram focadas em um único navegador (normalmente IE) ou
eram simulações de um navegador (como HttpUnit). O custo de uma
licença para uma ferramenta comercial teria esgotado o orçamento
limitado de um pequeno projeto interno, então eles nem mesmo
consideraram como uma alternativa viável. <BR><BR>Onde a automação
de testes se torna difícil, é comum recorrer à testes manuais.
Está abordagem não funciona quando a equipe é muito pequena ou
quando a liberação de novas versões é extremamente frequente. É
também uma falta de humanidade, pedir a uma pessoa que revise um
<U>código</U> que poderia ser automatizado. Comumente, pessoas são
mais lentas e mais susceptíveis à erros em tarefas repetitivas do
que máquinas. Teste manual não era um opção.<BR><BR>Felizmente,
todos os navegadores que foram testados <U>suportavam</U> Javascript.
Escrever um ferramenta de teste nesta linguagem, fez sentido para
Jason e a equipe com a qual ele trabalhava, pois esta poderia ser
usada para verificar o comportamento da aplicação. Inspirado pelo
trabalho feito no <U>FIT¹</U>, uma sintaxe baseada em tabelas
(<U>table-based</U>)<FONT COLOR="#0000ff"> </FONT>foi colocada sobre
o Javascript puro e isso permitiu que os testes fossem escritos por
pessoas com experiência limitada em programação usando uma
abordagem baseada em palavras chave (<U>keyword-based</U>) em
arquivos HTML. Esta ferramenta, originalmente chamada de “Selenium”
mas depois referenciada como “Selenium Core”, foi liberada em
2004 sob a licença Apache 2.<BR><BR>A formatação em tabelas do
Selenium é estruturada similarmente ao <U>ActionFixture presente</U>
no FIT. Cada linha da tabela é dividida em três colunas. A primeira
coluna contém o nome do comando a ser executado, a segunda coluna
tipicamente contém um elemento identificador e a terceira coluna
contém um valor opcional. Por exemplo, isto é como definir a string
“Selenium WebDriver” dentro de um elemento identificado pelo nome
“q”:<BR><BR>type name=q Selenium
WebDriver<BR><BR><BR>Pelo fato do Selenium ter sido escrito em
Javascript <U>puro</U>, seu design inicial requeria que os
desenvolvedores hospedassem o <U>Core</U> e seus testes no mesmo
servidor em que estava a aplicação a ser testada (AUT) para evitar
falhas grosseiras das politicas de segurança do navegador e do
Javascript <U>sandbox</U>. Isso nem sempre era prático ou possível.
E pior, ainda que a IDE dos desenvolvedores lhes desse habilidade
para rapidamente manipular o código e navegar pela extensa coleção
de códigos-fonte (codebade), não existe tal ferramenta para HTML.
Rapidamente se tornou claro que manter uma coleção de testes pela
metade era um <U>propósito</U> incômodo e doloroso.<BR><BR>Para
resolver este e outros problemas, um proxy HTTP foi escrito para que
toda solicitação HTTP pudesse ser interceptada pelo Selenium.
Usando este proxy, tornou-se possível desviar de muitas das
limitações da politica de “mesmo host de origem”, onde o
navegador não permitia que o Javascript fizesse nenhuma chamada para
qualquer outro lugar além do servidor a partir do qual a página
atual foi servida, permitindo que a primeira fraqueza fosse
suavizada. O design abriu a possibilidade de escrever a ligação
protocolo/adaptador de rede do Selenium em várias outras linguagens:
eles só precisavam ser capazes de enviar uma requisição HTML para
uma URL particular. O <U>wire format</U> foi <U>intimamente</U>
modelado de acordo com a sintaxe baseada em tabela do Selenium Core e
isto, juntamente com a sintaxe baseada em tabelas, tornou-se
conhecida como “Selenese”. Porque os <U>vínculos da linguagem</U>
estavam controlando o navegador à distância, a ferramenta foi
chamada de “Selenium Remote Control”, ou “Selenium
RC”.<BR><BR>Enquanto o Selenium estava sendo desenvolvido, outro
framework de automação de navegadores estava sendo preparado no
ThoughtWorks: WebDriver. O código inicial <U>deste</U> foi liberado
<U>precocemente</U> em 2007. WebDriver <U>derivou-se</U> do trabalho
em projetos que queriam <U>isolar a</U> <U>cobertura de testes da
base da ferramenta de testes</U>. Tipicamente, o caminho pelo qual
este isolamento é feito, é através do padrão <U>Adapter.</U>
WebDriver cresceu a partir do conhecimento desenvolvido pela
aplicação desta abordagem coerente ao longo de inúmeros projetos,
e inicialmente era uma capa em torno do HtmlUnit. O suporte do
Internet Explorer e do Firefox sucedeu-se rapidamente após o
lançamento.<BR><BR>Quando o WebDriver foi liberado, existiam
diferenças significantes entre este e o Selenium RC, apesar disto,
eles se mantiveram no mesmo nicho de software de uma API para
automação de navegadores. A diferença mais obvia para um usuário,
era que o Selenium RC tinha uma API baseada em dicionário, com todos
os métodos expostos em uma única classe, equanro o WebDriver tinha
uma API mais orientada a objetos. Além disso, WebDriver apenas
suportava Java, enquanto o Selenium RC oferecia suporte para uma
vasta quantidade de linguagens. Existiam também, fortes diferenças
técnicas: Selenium Core (no qual o RC foi baseado) era
essencialmente uma aplicação Javascript, rodando dentro do <U>sandbox</U>
de segurança do navegador. WebDriver tentou se vincular nativamente
ao navegador, contornando o modelo de segurança do navegador as
custas do significante aumento do esforço no desenvolvimento do
framework em si.<BR><BR>Em agosto de 2009, foi anunciado que os dois
projetos poderiam se fundir, e o Selenium WebDriver é o resultado
destes dois projetos unidos. Enquanto escrevo, o suporte de
linguagens do WebDriver foi aprimorado para Java, C#, Python e Ruby.
Isso oferesse suporte para Chrome, Firefox, Internet Explorer, Opera
e para os navegadores do Iphone e do Android. <U>Existem projetos
irmãos</U>, não mantidos no mesmo repositório de códigos-fonte,
mas trabalhando intimamente com o projeto principal, que fornecem as
ligações do Perl, umas implementações para o navegador do
BlackBerry, e para <U>WebKits</U> <U>“sem cabeça”</U> - <U>útil
para as horas em que os testes precisam ser rodados em um servidor de
integração continua sem uma exibição adequada</U>. O mecanismo
original do Selenium RC ainda é mantido e permite que o WebDriver
forneça suporte para os navegadores que seriam incompatíveis.
<BR><BR>16.2. Uma <U>Digresion</U> sobre Jargon<BR><BR>Infelizmente,
o projeto Selenium utiliza muitos <U>jargões</U>. Recapitulando o
que nós já vimos:</SPAN></FONT></FONT></P>
<UL>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Selenium
Core é o coração da implementação original do Selenium, e é um
conjunto de scripts Javascript que controlam o navegador. Esta,
algumas vezes é referenciado como “Selenium” e outras como
“Core”.</SPAN></FONT></FONT></P>
</UL>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<UL>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Selenium
RC foi o nome dado para as <U>ligações</U> das linguagens para o
Selenium Core, e é comumente, e confusamente, referenciada apenas
como “Selenium” or como “RC”. Agora, isto tem sido
substituido pot Selenium WebDriver, onde a API do RC é referenciada
como o “Selenium 1.x API”.</SPAN></FONT></FONT></P>
</UL>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<UL>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Selenium
WebDriver se encaixa no mesmo nicho que o RC <U>fez</U>, e tem
incluido as ligações originais do 1.x. Isso refere-se a ambos os
vinculos de linguagem e a implementação de códigos de controle
individual do navegador. Isto é comumente referenciado apenas como
“WebDriver” ou, algumas vezes, como Selenium 2. . Sem dúvida,
esta será contraida para “Selenium” ao longo do tempo.</SPAN></FONT></FONT></P>
</UL>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>O
leitor atento já terá percebido que “Selenium” é usado em um
sentido bastante geral. Felizmente, o contexto deixa claro qual
Selenium as pessoas estão se referindo em particular.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Finalmente,
existe mais uma frase que eu vou estar usando, e não há nenhuma
maneira graciosa de introduzi-la: “driver” é o nome dado para
uma implementação especifica da API do WebDriver. Por exemplo,
existe um driver do Firefox e um driver do Internet Explorer.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.
Enredos Arquitetônicos</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Antes
de começarmos a olhar as partes individuais para entender como eles
estão ligados, é útil entender o </FONT></SPAN><FONT SIZE=3><U>grande
enredo</U></FONT><SPAN STYLE="text-decoration: none"> </SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>da
arquitetura e desenvolvimento do projeto. Sucintamente, são eles:</FONT></SPAN></SPAN></FONT></P>
<UL>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Manter
os custos baixos.</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Emular
o usuário.</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Mostrar
que os drivers funcionam.</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; widows: 2; orphans: 2; text-decoration: none">
<SPAN STYLE="background: transparent">…<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">mas
você não precisa entender como tudo funciona.</SPAN></SPAN></FONT></FONT></SPAN></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent"><U>Deminuir
o </U><I><U>bus factor</U></I><U>.</U></SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Ter
simpatia por implementação em Javascript.</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Toda
chamada de método é uma chamada RPC.</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Nós
estamos em um projeto Open Source.</SPAN></FONT></FONT></P>
</UL>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><BR><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.1.
Manter os custos baixos</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Suportar
X navegadores em Y plataformas é inerentemente um propósito caro,
tanto em termos de desenvolvimento inicial, quanto em manutenção.
Se pudermos encontrar algum jeito para manter a qualidade do produto
alta sem violar muitos dos outros princípios, então esse é o
caminho a ser seguido. Isso é claramente visto em nossa adoção do
Javascript, onde for possível, como você vai ler sobre em
breve.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.2.
Emular o usuário</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>WebDriver
é desenhado para simular perfeitamente o modo que um usuário irá
interagir com uma aplicação web. Uma abordagem comum para simular a
entrada do usuário, é fazer uso do Javascript para sintetizar e
disparar uma série de eventos que um aplicativo veria se um usuário
real estivesse realizando a mesma interação. Esta abordagem de
“eventos sintetizados” é repleta de dificuldades em cada
navegador, e algumas vezes diferentes versões do mesmo navegador,
disparam eventos diferentes, com valores ligeiramente diferentes.
Para complicar, a maioria dos navegadores não permitem ao usuário
interagir desta forma com elementos de formulário, como elementos de
entrada de arquivos por razões de segurança.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Onde
é possível, WebDriver utiliza a abordagem alternativa de disparar
eventos no nível só SO. Como estes “eventos nativos” não são
geradados pelo navegador, esta abordagem contorna as restrições de
segurança colocadas em eventos sintetizados e, porque eles são
específicos do OS, uma vez que estão trabalhando para um navegador
em uma plataforma particular, reusar o código em um outro navegador
é relativamente fácil. Tristemente, esta abordagem só é possível
onde o WebDriver é capaz de se conectar estreitamente com o
navegador e onde o time de desenvolvimento determinou qual a melhor
forma de enviar eventos nativos sem que a janela do navegador esteja
em foco (como os testes no Selenium levam muito tempo para rodar, e
isto é útil para que seja possível utilizar a máquina para outras
tarefas enquanto eles rodam). </FONT></SPAN><FONT SIZE=3><U>Na hora
de escrever</U></FONT><SPAN STYLE="text-decoration: none"><FONT SIZE=3>,
isto significa que eventos nativos podem ser usados no Linux e no
Windows, mas não no Mac OS X.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Não
importa como o WebDriver está emulando a entrada do usuário,
estamos nos esforçando para imitar o comportamento do usuário,
tanto quanto possível. Em contraste como RC, que operava em um nível
muito inferior ao que o usuário trabalha.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.3.
Mostre que o drivers funcionam</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Pode
ser um idealismo, coisa de “maternidade e torta de maçã”, mas
eu acredito que não existe sentido em escrever códigos se estes não
funcionam. O jeito de provar que os drivers funcionam no projeto
Selenium é ter um amplo conjunto de casos de teste automatizado.
Estes são tipicamente “testes de integração”, exigindo que o
código seja compilado e faça uso de um navegador que interaja com
um servidor web, mas onde é possível, nós escrevemos “testes
unitátios”, os quais, diferente dos testes de integração, podem
rodar sem uma recompilação completa. </FONT></SPAN><FONT SIZE=3><U>Na
hora de esrever</U></FONT><SPAN STYLE="text-decoration: none"><FONT SIZE=3>,
há cerca de 500 testes de integração e cerca de 250 testes
unitários que poderiam ser rodados em cada navegador. Nós
adicionamos mais, à medida que concertamos falhas e escrevemos novos
códigos, e nosso foco está se deslocando para escrever mais testes
de unidade.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Nem
todo teste é executado em qualquer browser. Alguns recursos de
testes especificos que alguns navegadores não suportam, ou que são
tratadas de formas diferentes em diferentes navegadores. Exemplos
disso são os testes para os novos recursos do HTML5 que não são
suportados em todos os navegadores. Apesar disso, cada um dos mais
importantes navegadores tem um subconjunto significante de testes
rodados através deles. Compreensivelmente, encontrar um jeito de
rodar mais de 500 testes por navegador em múltiplas plataformas é
um desafio significativo, e é com isso que o projeto continua
lutando.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.4.
Você não precisa entender como tudo funciona</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Poucos
desenvolvedores são proficientes e confortáveis com as linguagens e
tecnologias que usamos. Consequentemente, nossa arquitetura precisa
permitir aos desenvolvedores focar onde seus talentos podem ser
melhor aproveitados, sem a necessidade de trabalharem em partes da
base de códigos onde se sentem inconfortáveis.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.5.
</FONT></SPAN><FONT SIZE=3><U>Diminua o </U></FONT><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>bus
factor</I></FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Há
um (não inteiramente sério) conceito no desenvolvimento de
softwares chamado “</FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>bus
factor</I></FONT></SPAN><SPAN STYLE="text-decoration: none">”</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>.
Refere-se ao numero de desenvolvedores-chave que devem cumprir um fim
terrível – aparentemente sendo atingido por um ônibus – </FONT></SPAN><FONT SIZE=3><U>para
deixar o projeto em um estado onde não poderia mais continuar</U></FONT><SPAN STYLE="text-decoration: none"><FONT SIZE=3>.
Algo tão complexo quanto automação de navegadores poderia ser
particularmente propensa a isso, então, muitas das nossas decisões
arquiteturais são feitas para este número tão alto quanto
possível.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.6.
Tenha simpatia por implementações em Javascript</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>WebDriver
</FONT></SPAN><FONT SIZE=3><U>falha</U></FONT><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>em usar
Javascript puro para conduzir o navegador se não existir outro jeito
de conduzi-lo. Isso significa que qualquer API que adicionarmos deve
ser “simpática” para uma implementação em Javascript. Como um
exemplo concreto, HTML5 introduz LocalStorage, uma API para
armazenamento de dados estruturados no lado do cliente.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.7.
Toda chamada é uma chamada RPC</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>WebDriver
controla navegadores que estão rodando em outros processos. Embora
seja fácil </FONT></SPAN><FONT SIZE=3><U>ignorá-lo</U></FONT><SPAN STYLE="text-decoration: none"><FONT SIZE=3>,
isso significa que toda chamada que é feita é uma chamada RPC,
então a performance do framework está a mercê da latência da
rede. Em uma operação normal, isso pode não ser terrivelmente
notável - a maioria dos OS’s otimiza o roteamento para o </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>localhost
- </I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>mas
como a latência entre o navegador e o código de teste aumenta, o
que poder ter parecido eficiente se torna menos tanto para os
designers quanto para os usuários desta API.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Isto
introduz uma certa tensão no projeto de APIs. Uma API maior, com
funções mais grosseiras, ajudaria a diminuir a latência </FONT></SPAN><FONT SIZE=3><U>derrubando</U></FONT><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>várias
chamadas, mas isso deve ser balanceado, mantendo a API expressiva e
fácil de usar. Por exemplo, há varias verificações que precisam
ser feitas para determinar se um elemento é visível para o usuário
final. Não só precisamos levar em consideração várias
propriedades do CSS, que podem precisar ser inferidos olhando seus
elementos pai, mas devemos checar também as dimensões do elemento.
Uma API minimalista exigiria que cada checagem fosse deita
individualmente. WebDriver detona todas elas com um único método
</FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>isDisplayed.</I></FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.3.8.
Pensamento Final: Isso é </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Open
Source</I></FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Embora
este não seja um ponto estritamente arquitetural, Selenium pe um
projeto </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Open
Source</I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>.
O tema que todos os pontos acima juntos é que nós gostariamos de
faze-lô tão fácil quanto possivel para que um novo desenvolvedor
possa contribuir. Mantendo a profundidade do conhecimento necessário
tão superficial quanto possivel, usando tão poucas linguagens
quanto necessário e contando com testes automatizados para verificar
que nada parou de funcionar, esperamos permitir que este seja de
fácil contribuição.</FONT></SPAN><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Originalmente
o projeto foi divido em uma série de módulos, com cada módulo
representando um navegador em particular com módulos adicionais para
códigos em comum e para suporte e utilidade do código. Árvores
fonte foram armazenadas sob estes módulos. Esta abordagem fez muito
sentido para linguagens como Java e C#, mas era doloroso para
trabalhar com Rubystas e Pythonistas. Isto se traduziu quase
diretamente em um número relativo de contribuidores, com pucas
pessoas interessadas em trabalhar nas partes de Python e Ruby. Para
resolver isso, em Outubro e Novenbro de 2010 o código fonte foi
reorganizado com o códigos Python e Ruby armazenados em um
diretório, na camada mais alta, para cada linguagem. Isto combinou
melhor com as expectativas dos desenvolvedores Open Source destas
linguagens, e o efeito nas contribuições da comunidade foi notável
quese que imediatamente.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.4
Lidando com a Complexidade</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Software
é uma construção irregular. Os nódulos são a complexidade, e
como designers de uma API nós temos uma escolha de onde jogar essa
complexidade. Em um xtremo, poderiamos dividir a complexidade da
maneira mais justa possivel, significando que cada consumidor dessa
API precisa ser parte disso. O outro extremo sugere pegar a maior
parte possível da complexidade e isola-la em um único local. Este
local seria um lugar de escuridão e terror para muitos se estes
tiverem que se aventurar lá, mas a questão é que os usuários da
API, que não precisam se aventurar na sua implementação, têm o
custo da complexidade pago à vista por eles.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Os
desenvolvedores do WebDriver tendem mais à encontrar e isolar a
complexidade em poucos lugares, ao invés de espalha-lá. Uma razão
para isso são nossos usuários. Eles são excepcionalmente bons em
encontrar problemas e falhas, como uma olhada em nossa lista de bugs
mostra, mas como a maioria deles não são desenvolvedores, uma API
complexa não iria funcionar muito bem. Nós procuramos fornecer uma
API que guia as pessoas na direção certa. Como um exemplo,
considere os seguintes métodos da API original do Selenium, cada
qual pode ser usada para definir o valor de entrada de um elemento:</FONT></SPAN></SPAN></FONT></P>
<UL>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">type</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">typeKeys</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">typeKeysNative</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">keydown</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">keypress</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">keyup</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">keydownNative</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">keypressNative</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">keyupNative</SPAN></FONT></FONT></P>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">attachFile</SPAN></FONT></FONT></P>
</UL>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Aqui
está o equivalente na API do WebDriver:</FONT></SPAN></SPAN></FONT></P>
<UL>
<LI><P STYLE="margin-bottom: 0cm; background: transparent; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">sendKeys</SPAN></FONT></FONT></P>
</UL>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Como
discutido anteriormente, isto destaca uma das maiores diferenças
filosóficas entre Rc e WebDriver, na qual o WebDriver se esforça
para emular o usuário, enquanto o RC oferece um nível mais baixo
que um usuário acharia difícil ou impossível de alcançar. A
distinção entre </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>typeKeys</I></FONT></SPAN><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>e
</FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>typeKeysNative
</I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>é
que o primeiro sempre usa eventos sintéticos, enquanto o último
atenta para o uso do robo AWT para definir a chaves. Lamentavelmente,
o robo AWT envia a tecla pressionada para qualquer janela que esteja
focada, que não precisa ser necessáriamento o navegador. Eventos
nativos do WebDriver, por outro lado, são enviados diretamente para
o identificador da janela, evitando a necessidade de manter o
navegador no foco.</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.4.1.
O Design do WebDriver</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>A
equipe refere-se a API do WebDriver como sendo “baseada em
objetos”. As interfaces são claramente definidas e tentam se
adequar a ter apenas uma regra ou responsabilidade, mas ao invés de
modelar cada simples tag HTML com sua própria classe, nós temos um
única interface </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>WebElement</I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>.
Ao seguir esta abordagem, desenvolvedores que estão usando um
interface com suporte à preenchimento automático podem ser guiados
ao próximo passo. O resultado é que a sessão de codificação pode
ser parecida com esta (em Java):</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>WebDriver
driver = new FirefoxDriver();<BR>driver.<user hits space></I></FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Neste
ponto, uma lista relativamente pequena de 13 métodos aparece. O
usuário escolhe uma:</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>driver.findElement(<user
hits space>)</I></FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Agora,
a maioria das IDEs irá mostrar uma dica sobre o tipo de argumento
esperado, neste caso um </FONT></SPAN><U>“</U><FONT SIZE=3><U>By”</U></FONT><SPAN STYLE="text-decoration: none"><FONT SIZE=3>.
Há uma série de métodos pré-configurados para objetos do
tipo “By”, declarados como métodos estáticos em “By”. Noss
usuário rapidamente terminará com uma linha de código parecida com
esta:</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>driver.findElement(By.id("some_id"));</I></FONT></SPAN></SPAN></FONT></P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">INTERFACES
BASEADAS EM FUNÇÕES</SPAN></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Pense
em uma classe simplificada </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Shop.
</I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Todos
os dias, ela precisa ser reabastecida, e trabalha em conjundo com um
</FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Stockist
</I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>para
suprir o novo stock. Todos os meses, ela precisa pagar os empregados
e os impostos. Por uma questão de argumento, vamos que ele faz isso
usando um </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Accountant</I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>.
Uma forma de modalá-lo é:</FONT></SPAN></SPAN></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><I><SPAN STYLE="background: transparent">public
interface Shop {</SPAN></I></FONT></FONT></P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><I><SPAN STYLE="background: transparent">void
addStock(StockItem item, int quantity);</SPAN></I></FONT></FONT></P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><I><SPAN STYLE="background: transparent">Money
getSalesTotal(Date startDate, Date endDate);</SPAN></I></FONT></FONT></P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><I><SPAN STYLE="background: transparent">}</SPAN></I></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Nós
temos duas escolhas sobre onde colocar os limites na hora de definir
a interfaxe entre o Shop, o Accountant e o Stockist. Nós poderiamos
desenhar uma linha teórica, como é mostrado na figura 16.1.</SPAN></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Isso
significa que tanto </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Account</I></FONT></SPAN><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>quanto
</FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Stockist</I></FONT></SPAN><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>aceitariam
</FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>Shop
</I></FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>como
um argumento de seus respectivos métodos. A desvantagem aqui, porém,
é que é improvável que o Accountant realmente quer amontoar
</FONT></SPAN><FONT SIZE=3><U>SHELVES</U></FONT><SPAN STYLE="text-decoration: none"><FONT SIZE=3>,
e provavelmente não é uma boa idéia para o Stockist, realizar a
ampla </FONT></SPAN><FONT SIZE=3><U>checagem</U></FONT><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>nos preços
que o Shop está adicionando. Então, a lugar melhor para desenhar a
linha é mostrana na figura 16.2.</FONT></SPAN></SPAN></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Nós
precesaremos de duas interfaces que o Shop precisa implementar, mas
estas interfaces definem claramente o papel que o Shop cumpre, tanto
para o Accountant, quanto para o Stockist. Elas são interfaces
baseadas em funções:</SPAN></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><I><SPAN STYLE="background: transparent">public
interface HasBalance {<BR> Money getSalesTotal(Date
startDate, Date endDate);<BR>}<BR><BR>public interface Stockable
{<BR> void addStock(StockItem item, int
quantity);<BR>}<BR><BR>public interface Shop extends HasBalance,
Stockable {<BR>}</SPAN></I></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Acho
</FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>UnsupportedOperationExceptions</I></FONT></SPAN><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>e suas
classes profundamente desagradáveis, mas é preciso haver algo que
permita que a funcionalidade seja exposta para o subconjunto de
usuários que podem vir a precisar dela, sem sobrecarregar o restante
da API para o restante dos usuários. Em fim, WebDriver faz um
extenso uso de insterfaces baseadas em funções. Por exemplo. há
uma interface </FONT></SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3><I>JavascriptExecutor</I></FONT></SPAN><SPAN STYLE="text-decoration: none">
</SPAN><SPAN STYLE="text-decoration: none"><FONT SIZE=3>que provê a
habilidade de executar blocos arbitrários de Javascript no contexto
da página atual. Um lançamento perfeito de uma instância do
WebDriver para aquela interface, indica que você pode esperar que os
métodos desta funcionem.</FONT></SPAN></SPAN></FONT></P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Figura
16.1: Accountant e Stockinst dependem de Shop</SPAN></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-left: 1.24cm; margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Figura
16.2: Shop implementa HasBalance e Stockable</SPAN></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman"><SPAN STYLE="background: transparent"><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>16.4.2.
Lidar com a explosão combinatória</FONT></SPAN><BR><BR><SPAN STYLE="text-decoration: none"><FONT SIZE=3>Uma
das primeiras coisas que resulta um momento de reflexão sobre a
vasta gama de navegadores e linguagens que o WebDriver suporta, é
que a menos que se tenha cuidado, os custos de manutenção podem
tomar um caminho crescente. Com X navegadores e Y linguagens, seria
fácil cair na armadilha de manter XxY implementações.<BR><BR>Reduzir
o número de linguagens suportadas pelo WebDriver seria uma maneira
de reduzir seus custos, mas não queremos pegar este caminho por dois
motivos. Primeiramente, existe uma carga cognitiva a ser paga quando
se muda de uma linguagem para outra, por isso é vantajoso para os
usuários do framework poderem escrever seus testes na mesma
linguagem em que utilizam na maior parte do projeto no qual
trabalham. Em segundo lugar, misturar muitas linguagens em um simples
projeto é algo que não vai deixar a equipe confortável, e padrões
de codificação corporativa e requerimentos frequentemente parecem
demandar um tecnologia monocultura (embora, agradável, ei penso que
esta segunda opção está se tornando menos verdadeira ao longo do
tempo), contudo reduzir o número de linguagens suportadas não é
uma opção disponível.</FONT></SPAN></SPAN></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2; text-decoration: none">
<FONT FACE="Times New Roman"><FONT SIZE=3><SPAN STYLE="background: transparent">Reduzir
o numero de navegadores suportados também não é uma opção
disponível – haviam fortes argumentos quando eliminamos o suporte
ao Firefox 2 no WebDriver, apesar do fato de que quando fizemos essa
escolha, representava menos de 1% do mercado de navegadores.</SPAN></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">A única escolha
que nos resta é tentar e fazer todos os navegadores parecerem
idênticos para as ligações da linguagem: eles devem oferecer um
interface uniforme que pode ser facilmente tratada em uma ampla
variedade de linguagens. Além do mais, queremos as ligações das
linguagens em si sejam tão fáceis de escrever quanto possível. Nós
empurramos, tanta lógica quanto pudemos, para o drive subjacente, a
fim de apoiar esta: cada pedaço de funcionalidade que nós falhamos
em colocar dentro do driver é algo que precisa ser implementado em
todas as linguagens que damos suporte, e isso pode representar uma
quantidade significativa de trabalho.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Como um exemplo,
o driver do IE foi, com sucesso, alocado à responsabilidade de
localizar e iniciar o IE, dentro do driver lógico principal. Contudo
isso resultou em um surpreendente numero de linhas de código no
driver, as ligações da linguagem para criar uma nova instância
resume-se em uma simples chamada de método dentro do driver. Para
comparação, o driver do Firefox não conseguiu fazer esta
alteração. No mundo Java por si só, isso significa que nós temos
três classes principais que tratam de configurar e iniciar o
Firefox, pesando em torno de 1300 linhas de código. Estas classes
são duplicadas em toda as linguagens que querem suportar o driver do
Firefox sem precisar levantar um servidor Java. Isso é bastante
código adicional para manter.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">16.4.3. Falhas
no design do WebDriver</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">O lado ruim da
decisão de expor os recursos desta forma, é que até que alguém
saiba que existe uma interface especifica, eles podem não perceber
que o WebDriver suporta este tipo de funcionalidade; há uma perda de
usabilidade na API. Certamente quando o WebDriver era novo, nós
parecíamos perder muito tempo apenas dirigindo as pessoas para
interfaces especificas. Nós pomos agora muuito mais esforço em
nossa documentação e como a API se tornou mais usada se torna fácil
de usar e fácil para os usuários encontrarem a informação que
precisam.
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Há um lugar
onde eu penso que nossa API é particularmente pobre. Nós temos uma
interface chamada <FONT FACE="Courier 10 Pitch"><FONT SIZE=2>RenderedWebElement</FONT></FONT>
que tem uma estranha miscelânea de métodos para fazer a consulta do
estado do elemento renderizado (<FONT FACE="Courier 10 Pitch">isDisplayed</FONT>,
<FONT FACE="Courier 10 Pitch">getSize</FONT> and <FONT FACE="Courier 10 Pitch">getLocation</FONT>),
realizando operações sobre ele ( <FONT FACE="Courier 10 Pitch">hover</FONT>
e methodos para arrastar e soltar), e um método útil para obter o
valor de uma propriedade CSS em particular. Ele foi criado porque o
driver HtmlUnit não expunha as informações desejadas, mas os
drivers do Firefox e do IE expuseram. Originalmente havia apenas o
primeiro conjunto de metodos mas nós adicionamos os outros métodos
antes de eu ter pensado muito sobre como eu queria que a API
evoluísse. A interface é bem conhecida agora, e a escolha mais
difícil é se mantemos esta extremidade feia da API dado que esta é
amplamente usada, ou se tentamos deletá-la. Minha preferencia é não
deixar uma “janela quebrada” para trás, então é importante
concertá-la antes de liberarmos o Selenium 2.0. Como um resultado,
enquanto você lê este capitulo, RenderedWebElement pode muito bem
ter ido embora.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Do ponto de
vista do implementador, uma forte ligação com o browser também é
uma falha de design, apesar de não termos outra escolha. Isto
consome um esforço significante para suportarmos um novo browser, e
frequentemente vários esforços necessitam ser feitos para que tudo
ocorra bem. Como um exemplo concreto, o driver do Chrome foi
reescrito quatro vezes, e o driver do IE, três. A vantagem de se
estabelecer uma forte ligação com o browser é que se tem mais
controle sobre o mesmo.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">16.5. Camadas e
Javascript</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Uma ferramenta
de automação de navegadores é costituida essencialmente por três
partes:</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<UL>
<LI><P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Uma maneira
de interrogar o DOM</P>
<LI><P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Um
mecanismo para executar o Javascript</P>
<LI><P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Alguns
métodos para simular a entrada do usuário</P>
</UL>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Esta sessão
foca na primeira parte: provendo um mecanismo para interrogar o DOM.
A língua franca do navegador é o Javascript, e esta parece ser a
linguagem ideal a ser usada ao interrogar o DOM. Embora esta escolha
pareça obvia, utilizá-la nos leva a alguns desafios e requisitos
concorrentes que precisam ser equilibrados quando pensamos sobre
Javascript.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Como muitos
grandes projetos, Selenium faz uso de um conjunto de bibliotecas em
camadas. A camada inferior é a biblioteca Clojure do Google, que
prove suprimentos primitivos e um mecanismo de modularização
permitindo que os arquivos-fonte sejam mantidos no foco e tão
pequenos quanto possível. Acima desta, há uma biblioteca de
utilitários fornecendo funções que vão desde simples tarefas,
como pegar o valor de um atributo, determinando se um elemento seria
visível a um usuário final, para ações muito mais complexas como
simular um click usando eventos sintetizados. Dentro do projeto,
estes são vistos como oferecendo as menores unidades de automação
de navegadores, e assim são chamados de Átomos de Automção de
Navegadores ou somente átomos. Finalmente, existem camadas de
adaptação que compõem os átomos, a fim de atender os contratos da
API de ambos WebDriver e Core.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Figura 16.3:
Camadas da biblioteca de Javascript do Selenium</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">A biblioteca
Clojure foi escolhida por muitas razões. A principal delas era que o
compilador do Clojure compreendia a técnica de modularização da
biblioteca utilizada. O compilador Clojure direciona o Javascript
como uma linguagem de saída. “Compilação” pode ser tão
simples quanto ordenar arquivos de entrada pela ordem das
dependências, concatenando e imprimindo-os, ou tão complexo como
fazer uma minificação avançada e remove código morto. Outra
vantagem inegável era que muitos membros da equipe que trabalhava no
código Javascript estavam familiarizados com a biblioteca Clojure.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Esta biblioteca
“atômica” de código é profundamente usada em toda parte do
projeto onde existe a necessidade de interrogar o DOM. Para o RC e
aqueles driver compostos, em grande parte, de Javascript, a
biblioteca é usada diretamente, tipicamente compilada como um script
monolítico. Para drivers escritos em Java, funções individuais da
camada de adaptação do WebDriver são compiladas com a otimização
plena habilitada, e o Javascript gerado é incluido como um recurso
nos JARs. Para drivers escritos nas variações do C, como o Iphone e
os drivers do IE, não só as funções individuais são compiladas
com otimização plena, mas a saída gerada é convertida para uma
constante definida no cabeçalho que é executado pelo mecanismo de
execução do Javascript sempre que necessário.
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Pelo fato dos
átomos serem amplamente usados, é possível garantir um
comportamento consistente entre os diferentes navegadores, e porque a
biblioteca é escrita em Javascript e não exige privilégios
elevados para executar o ciclo de desenvolvimento, é fácil e
rápido. A biblioteca Clojure pode carregar dependências
dinamicamente, então o desenvolvedor do Selenium só precisa
escrever um teste e carregá-lo em um navegador, modificando o código
e pressionando o botão de refresh conforme necessário. Uma vez que
os testes estão passando em um navegador, é fácil carregá-los em
outro navegador e confirmar que este passa também. Porque a
biblioteca Clojure faz um bom trabalho abstraindo as diferenças
entre os navegadores, isso muitas fezes é suficiente, apesar disso,
é reconfortante saber que existem construções continuas que irão
executar o conjunto de teste em todos os navegadores suportados.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Originalmente o
Core e o WebDriver possuíam muitas áreas de códigos congruentes –
códigos que realizavam a mesma função de maneiras ligeiramente
diferentes. Quando começamos a trabalhar nos átomos, foi vasculhado
para tentarmos encontrar a funcionalidade “mais educada”. Afinal,
ambos os projetos foram amplamente usados e seus códigos eram muito
robustos para jogarmos tudo fora e começar do zero não só teria
sido um desperdício, mas também um tolice. Como cada átomo foi
extraído, os locais em que seriam usados foram identificados e
passou a usar o átomo. Por exemplo, o método <FONT FACE="Courier 10 Pitch">getAttribute</FONT>
do driver do Firefox encolheu em cerca de 50 linhas de código para 6
linhas longas, incluindo linhas em branco:</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<PRE CLASS="western" STYLE="font-style: normal; font-weight: normal; widows: 2; orphans: 2"><FONT FACE="sans-serif">FirefoxDriver.prototype.getElementAttribute =</FONT>
<FONT FACE="sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">function(respond, parameters) {</SPAN></SPAN></FONT>
<FONT FACE="sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">var element = Utils.getElementAt(parameters.id,</SPAN></SPAN></FONT>
<FONT FACE="sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">respond.session.getDocument());</SPAN></SPAN></FONT>
<FONT FACE="sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">var attributeName = parameters.name;</SPAN></SPAN></FONT>
<FONT FACE="sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">respond.value = webdriver.element.getAttribute(element, attributeName);</SPAN></SPAN></FONT>
<FONT FACE="sans-serif"><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">respond.send();</SPAN></SPAN></FONT>
<FONT FACE="sans-serif">};</FONT></PRE><P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">
Aquela penúltima linha, onde <FONT FACE="sans-serif"><FONT SIZE=2><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">respond.value</SPAN></SPAN></FONT></FONT>
é atribuída, está usando a biblioteca atômica do WebDriver.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Os atoms são
uma demostração pratica de muitos dos temas arquiteturais do
projeto. Naturalmente eles obrigam a obedecer a necessidade que um
implementação de uma API tem de ser favorável à uma implementação
em Javascript. O que é ainda melhor, que a mesma biblioteca é
compartilhada em toda o código-fonte; onde uma vez um bug teve de
ser verificado e consertado em múltiplas implementações, agora,
corrigir o bug em apenas um lugar já é suficiente, o que reduz o
dispêndio de mudanças enquanto são melhoradas a instabilidade e a
efetividade. Os atoms também fazem o bus factor do projeto mais
favorável. Uma vez que um teste unitário normal em Javascript pode
ser usado para verificar se uma correção funciona a barreira para a
adesão ao projeto Open Source é consideravelmente menor do que era
quando o conhecimento de cada piloto foi implementado como era
necessário.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Há outro
beneficio em usar os atoms. Uma camada emulando uma implementação
RC existente, mas apoiada pelo WebDriver, é uma importante
ferramenta para as equipes que procuram migrar de forma controlada
para a novas APIs do WebDriver. Como o Selenium Core é atomizado, se
torna possível compilar cada função dele individualmente, tornando
a tarefa de escrever a camada de emulação tanto mais fácil quanto
mais preciso.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Continuamos sem
dizer que há desvantagens para esta abordagem. Mais importante
ainda, compilar Javascript para uma const C, é uma coisa muito
estranha de se fazer e sempre confunde novos colaboradores para o
projeto que querem trabalhar no Código C. Também é raro um
desenvolvedor que tem cada versão de cada navegador e é dedicado o
suficiente para rodar cada teste em todos aqueles navegadores – é
possível que alguém, inadvertidamente, cause uma regressão em um
lugar inesperado, e isso pode custar algum tempo para identificar o
problema, especialmente se as compilações continuas estiverem
esquisitas.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Por causa do
átomos normalizarem os valores de retorno entre os navegadores,
também podem haver valores de retorno inesperado. Por exemplo,
considere este HTML:</P>
<PRE CLASS="western" STYLE="margin-bottom: 0.5cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2"><FONT FACE="sans-serif"><input name="example" checked></FONT></PRE><P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">
<BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">O valor do
atributo <FONT COLOR="#000000"><FONT FACE="sans-serif"><FONT SIZE=2><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">checked
</SPAN></SPAN></FONT></FONT></FONT><FONT COLOR="#000000"><FONT FACE="Times New Roman, serif"><FONT SIZE=3><SPAN STYLE="font-style: normal"><SPAN STYLE="font-weight: normal">dependerá
do navegador que está sendo usado. Os atoms normalizam isso, e
outros atributos Booleanos definidos nas especificações do HTML5,
para ser “Verdadeiro” ou “Falso”. Quando esse atom foi
introduzido para o códigos-fonte, nós descobrimos vários lugares
onde as pessoas estavam fazendo suposições sobre qual deveria ser o
valor de retorno, dependendo do navegador. Enquanto o valor foi agora
consistente, ouve um longo período onde nós explicamos para a
comunidade o que havia acontecido e porque.</SPAN></SPAN></FONT></FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; font-style: normal; font-weight: normal; widows: 2; orphans: 2">
<FONT FACE="Times New Roman, serif"><FONT SIZE=3>16.6. O Driver
Remoto e o Driver do Firefox em Particular</FONT></FONT></P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">O WebDriver
remoto foi originalmente um mecanismo RPC glorificado. Desde então
tem evoluído para um mecanismo chave que usamos para reduzir os
custos de manutenção, provendo uma interface uniforme que as
ligações das linguagens podem codificar. Mesmo sabendo que nós
retiramos a maior parte da lógica das ligações de linguagem e
colocamos dentro do driver, se cada driver precisasse se comunicar a
partir de um único protocolo, nós ainda teríamos uma grande
quantidade de código para repetir através das ligações de
linguagem.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">O protocolo
remoto do WebDriver é usado em qualquer lugar onde precisarmos nos
comunicar com a instancia de um navegador que está rodando em outro
processo. Projetar este protocolo, significou levar em conta várias
preocupações. Muitas delas eram técnicas, mas, sendo este um
projeto de código aberto, havia também o aspecto social para ser
considerado.
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Qualquer
mecanismo RPC é dividido em duas partes: o transporte e a
codificação. Nós sabíamos que, por mais que tivéssemos
implementado o protocolo remoto do WebDriver, nós precisaríamos de
suporte para ambas as partes, nas linguagens que fossem usadas como
cliente. A primeira iteração do projeto foi desenvolvida como uma
parte do driver do Firefox.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Mozilla, e
portanto Firefox, sempre foram vistos como sendo uma aplicação
multiplataforma, por seus desenvolvedores. Para facilitar o
desenvolvimento, Mozilla criou um framework inspirado no COM da
Microsoft, que permitia a criação e união dos componentes, chamado
XPCOM (cross-plataform COM). Uma interface XPCOM é definida usando
IDL, e há suporte para C e Java, tanto quanto para outras
linguagens. Por que o XPCOM é usado para construir o Firefox, e por
que o XPCOM tem suporte à Javascript, é possível fazer uso dos
objetos do XPCOM nas extensões do Firefox.</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2"><BR>
</P>
<P STYLE="margin-bottom: 0cm; widows: 2; orphans: 2">Win32 COM
normais permitem o acesso remoto as interfaces. Haviam planos pra
adicionar a mesma funcionalidade ao XPCOM também, e Darin Fisher uma
implementação do XPCOM ServerSocket para facilitar. Apesar de os
planos para o D-XPCOM nunca se tornarem realidade, como um anexo, os
vestígios da sua infraestrutura ainda estão lá.
</P>
</BODY>
</HTML>