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
|
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="content-type">
<title>Developing Drivers</title>
</head>
<body>
<h2>Overview</h2>
This page details important information for people developing drivers
for Selenium.<br>
<h2>Same Origin Policy</h2>
This is a security issue that affects all modern browsers. It is well
described <a
href="http://www.mozilla.org/projects/security/components/same-origin.html">here</a>,
but for our purposes, it constrains the way that a
JavaScript in a browser may interoperate with other open frames and
windows. In short, the Selenium JavaScript app must come from (or
appear to) the same origin as the AUT.<br>
<h2>The Driver</h2>
The driver has a number of duties. These are typically.. <br>
<ul>
<li>Instantiating the web server with a dynamic app (servlets for
Java) </li>
<li>Launching a browser with a with a URL that makes sense for
connecting to that server </li>
<li>providing an API to such that commands can be routed though the
dynamic app to the browser</li>
</ul>
<h2>Local, Remote and URLs<br>
</h2>
An application may be testable in a remote location by humans, but for
scripted testing and the need for the driver to dynamically drive the
browser, it is optimal for the driver to be on the same machine as that
serving the AUT and the browser testing it. <br>
<br>
Thus, an application as deployed ...<br>
<br>
<img alt="http://localhost:8080/" src="images/stockmeister.png"
style="width: 361px; height: 68px;"><br>
<br>
... would appear like so for the purposes of testing ...<br>
<br>
<img alt="http://localhost:8080/" src="images/localhostAut.png"
style="width: 346px; height: 43px;"><br>
<br>
As with the standalone version of Selenium, there are a number of files
(HTML and JavaScript) that comprise the bulk of the testing framework
and sit in the browser as testing occurs. It makes most sense to put
these in a virtual directory on the same server ...<br>
<br>
<img alt="http://localhost:8080/selenium/"
src="images/localhostSelenium.png"
style="width: 326px; height: 57px;"><br>
<br>
The dynamic webapp needs to be similarly mounted ...<br>
<br>
<img alt="http://localhost:8080/selenium/driver?..."
src="images/localhostDriver.png" style="width: 318px; height: 52px;"><br>
<br>
As the dynamic is the link between what is happening in the browser and
the driving process, it we need to somehow have an instance reference
to it. This is easier in some languages and web servers than
others. Also full programatic start/stop control over the web
server is not always possible for some larger web servers
implementations.<br>
<h2>Reply/Request Architecture</h2>
Because a browser cannot open a socket and listen on it, we must
effectively initiate communication thru the driver on the browser side.
Ignoring the possibilities granted by keep-alive, we simply poll from
the browser to the server and pick up commands to process inside the
browser. Results of commands are also passed back to the dynamic
hander over the same mechanism. These are in fact done in the same HTTP
request. The results from the <span style="font-style: italic;">previous</span>
command go back as query string parameters, and the <span
style="font-style: italic;">next</span> command is communicated in a
text/plain document<br>
<br>
The previous/next business introduces some complexity on the driver
side of the design. Namely hidden behind the API, the driver must
manage queues for the outgoing commands and the (some time later)
incoming responses. Java, until 1.5, did not have a blocking
queue to make this easy. Most other languages did.<br>
<h2><span style="font-weight: bold;">Selenese</span></h2>
<table style="width: 100%;" border="1" cellpadding="2" cellspacing="2">
<tbody>
<tr>
<td>Selenese is the contrived (and mostly hidden) wire language
that the
driver uses to speak to the browser-bot through the dynamic
handler. It uses HTTP for its transport, and is quite
simple. <br>
<br>
Responses come from the browser to the driver in a query
string like <br>
<br>
<span style="font-family: monospace;">commandResult=OK</span>, <br>
<br>
Commands go from the driver to the
browser-bot in a text/plain document:<br>
<br>
<span style="font-family: monospace;">| open | /foo/bar.html | |</span><br
style="font-family: monospace;">
<br>
This two way communication is of course invisible to the observer.</td>
<td style="width: 30%; background-color: rgb(255, 153, 102);">The
BrowserBot, by understanding Selenese, allows a process other than the
browser itsself to direct events on the Application Under Test. <br>
<br>
The Selenese language is simple enough to be commandable by any
language that has an API that can handle HTTP requests. <br>
<br>
Thus, Selenese allows many different open, free or closed license
drivers to interoperate with the BrowserBot.</td>
</tr>
</tbody>
</table>
<h2>Choregraphy</h2>
The driver cleary has some fairly heavy things to do. It is
important for some robustness to be built into the design. For example
it may take a long time for the browser to be instantiated on a
particular platform. It is appropriate for wait timeouts to be
generous here. Similarly whilst issuing individual commands it is
important for the driver to wait a sufficient amount of time for a
command to execute (and its result to come back). For the most
part on a localhost setup, it will be because the AUT is slow, but it
could be because some break in the app means that there will be no
subsequent response. Some timeout regime should be able to
recover from, mark a test as failed (for reasons of timeout), and start
again with the next test.<br>
<br>
<br>
</body>
</html>
|