-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathassertj-swing-lookup.html
349 lines (289 loc) · 18.3 KB
/
assertj-swing-lookup.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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="AssertJ site">
<meta name="author" content="Joel Costigliola">
<title>AssertJ / Fluent assertions for java</title>
<!-- CSS -->
<link rel="stylesheet" type="text/css" href="http://fonts.googleapis.com/css?family=Inconsolata|Source+Code+Pro|Open+Sans|Ubuntu|Varela+Round|Karla">
<link href="css/bootstrap.min.css" rel="stylesheet">
<link href="font-awesome/css/font-awesome.min.css" rel="stylesheet">
<script src="highlight/highlight.pack.js"></script>
<link rel="stylesheet" href="highlight/styles/railscasts.css">
<script>hljs.initHighlightingOnLoad();</script>
<link href="css/assertj.min.css" rel="stylesheet">
<link rel="shortcut icon" href="favicon.png" />
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- You'll want to use a responsive image option so this logo looks good on devices - I recommend using something like retina.js (do a quick Google search for it and you'll find it) -->
<a class="navbar-brand" href="index.html">AssertJ</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse navbar-ex1-collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="assertj-core-quick-start.html">Quick start</a></li>
<li><a href="assertj-news.html">News</a></li>
<li><a href="assertj-core.html">Core</a></li>
<li><a href="assertj-assertions-generator.html">Assertions generator</a></li>
<li><a href="assertj-guava.html">Guava</a></li>
<li><a href="assertj-joda-time.html">Joda-Time</a></li>
<li><a href="assertj-db.html">DB</a></li>
<li><a href="assertj-neo4j.html">Neo4j</a></li>
<li><a href="assertj-swing.html">Swing</a></li>
<li><a href="assertj-help.html">Help</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row" >
<div class="col-md-2 assertj-sidebar-menu">
<div class="bs-sidebar hidden-print affix-top" role="complementary">
<ul class="bs-sidenav nav ">
<li class="sidenav-header">About</li>
<li><a href="assertj-swing.html">Overview</a></li>
<li><a href="assertj-swing-quick-start.html">Quick start</a></li>
<li><a href="assertj-swing-news.html">News & releases</a></li>
<li><a href="swing/api/index.html">Javadoc</a></li>
<li><a href="assertj-swing.html#code">Code & issues <i class="fa fa-github"></i></a></li>
<li><a href="assertj-swing.html#contributing">Contributing</a></li>
<li class="sidenav-header">Working with it</li>
<li><a href="assertj-swing-getting-started.html">Getting started</a></li>
<li><a href="assertj-swing-basics.html">Basics</a></li>
<li><a href="assertj-swing-edt.html">EDT</a></li>
<li><a href="assertj-swing-lookup.html">Component lookup</a></li>
<li><a href="assertj-swing-launch.html">Launching</a></li>
<li><a href="assertj-swing-input.html">Input simulation</a></li>
<li><a href="assertj-swing-running.html">Running tests</a></li>
<li><a href="assertj-swing-troubleshooting.html">Troubleshooting</a></li>
<li><a href="assertj-swing-advanced.html">Advanced features</a></li>
<li class="sidenav-header">Migrating</li>
<li><a href="assertj-swing-migrating.html">From Fest</a></li>
</ul>
</div>
</div>
<div class="col-lg-10 col-md-10 col-sm-10 text-left" >
<h1 class="page-header">Component Lookup</h1>
<p>To test a GUI, we first need to find the components we want to perform user input simulation on or state
verification. This section explains how to find GUI components in AssertJ Swing.</p>
<h3 class="page-header"><span id="lookup-types"></span>Types of GUI Component Lookup</h3>
<p>To simulate user input on a GUI, AssertJ Swing first needs to find the GUI component(s) that will
participate in the test. For example, to simulate a user pressing a <em>ok</em> button, AssertJ Swing
first needs to find that button. AssertJ Swing provides different ways to lookup a GUI component:</p>
<h4>Lookup by name</h4>
<p>Using a unique name for GUI components guarantees that we can always find them, regardless of any change in
the GUI (as long as the components have not been removed). For example, to find a button having the name
<code>ok</code>, we need to set that name in the button before we execute our tests:</p>
<pre><code class="language-java">JButton okButton = new JButton("OK");
okButton.setName("ok");</code></pre>
<h4>Lookup by type</h4>
<p>Finding components by type is reliable as long as the GUI under test has only one component of such type.</p>
<h4>Lookup using a GenericTypeMatcher</h4>
<p>There are times when the GUI under test does not provide unique names for their components (e.g. legacy
applications). To overcome this limitation, AssertJ Swing provides a way to specify custom search
criteria using a <code>GenericTypeMatcher</code>. In this example we create a <code>GenericTypeMatcher</code>
that matches a <code>JButton</code> containing the text <code>OK</code>:</p>
<pre><code class="language-java">GenericTypeMatcher<JButton> textMatcher = new GenericTypeMatcher<JButton>(JButton.class) {
@Override protected boolean isMatching(JButton button) {
return "OK".equals(button.getText());
}
};</code></pre>
<div class="panel panel-info">
<div class="panel-heading">Note</div>
<div class="panel-body">
<code>GenericTypeMatcher</code> guarantees that the component passed as argument in the method
<code>isMatching(Component)</code> is never <code>null</code>.
</div>
</div>
<h3 class="page-header"><span id="component-matchers"></span>Common Component Matchers</h3>
<p>By default, AssertJ Swing supports <a href="#lookup-types">looking up components by name, type and
custom search criteria</a>. To specify
custom search criteria, users need to provide an implementation of <code>GenericTypeMatcher</code> or
<code>ComponentMatcher</code>.</p>
<p>AssertJ Swing provides some common-use component matchers in the package
<code>org.assertj.swing.core.matcher</code>:</p>
<dl class="dl-horizontal">
<dt><code>DialogMatcher</code></dt>
<dd>Matches a <code>Dialog</code> containing the specified name, title or visibility</dd>
<dt><code>FrameMatcher</code></dt>
<dd>Matches a <code>Frame</code> containing the specified name, title or visibility</dd>
<dt><code>JButtonMatcher</code></dt>
<dd>Matches a <code>JButton</code> containing the specified name, title or visibility</dd>
<dt><code>JLabelMatcher</code></dt>
<dd>Matches a <code>JLabel</code> containing the specified name, title or visibility</dd>
<dt><code>JTextComponentMatcher</code></dt>
<dd>Matches a <code>JTextComponent</code> containing the specified name, title or visibility</dd>
</dl>
<h4>Example</h4>
<p>The following example shows how to find and click a <code>JButton</code> with name <code>ok</code> and text
<code>Ok</code>, in a <code>JFrame</code> using a <code>JButtonMatcher</code>:</p>
<pre><code class="language-java">// import static org.assertj.swing.core.matcher.JButtonMatcher.withText;
FrameFixture window = new FrameFixture(robot(), frame);
window.show();
window.button(withName("ok").andText("OK")).click();</code></pre>
<h3 class="page-header"><span id="performing"></span>Performing GUI Component Lookup</h3>
<p>Regardless of the lookup type, AssertJ Swing provides two ways to perform GUI component lookup</p>
<h4>Using a <code>ContainerFixture</code></h4>
<p>The abstract class
<a href="swing/api/org/assertj/swing/fixture/ContainerFixture.html" target="_blank">ContainerFixture</a>
provides shortcuts to look up GUI components inside the <code>Container</code> being tested. There are three
overloaded versions of each shortcut method, one for each component lookup type (by name, type or
<code>GenericTypeMatcher</code>).</p>
<p>The following example uses a <code>FrameFixture</code>, a concrete implementation of
<code>ContainerFixture</code>, to look up a <em>login</em> <code>JButton</code> by name, type and custom
search criteria:</p>
<pre><code class="language-java">// by name
JButtonFixture button = window.button("login");
// by type
JButtonFixture button = window.button();
// custom search criteria (the button's text)
JButtonFixture button = window.button(new GenericTypeMatcher<JButton>(JButton.class) {
@Override
protected boolean isMatching(JButton button) {
return "Login".equals(button.getText());
}
});</code></pre>
<h5>Scope of component lookups</h5>
<p>By default, only components that are showing on the screen can participate in component lookups (except for
<code>JMenuItem</code>, which are not showing until they are selected). To change the scope of component
lookups, simply call the method <code>componentLookupScope(ComponentLookupScope)</code> in
<code>Settings</code>. All instances of <code>Robot</code> contain their own <code>Settings</code>,
which is returned by the method <code>settings()</code>. For more information about component lookup
scope, please read <code>ComponentLookupScope</code>'s
<a href="swing/api/org/assertj/swing/core/ComponentLookupScope.html" target="_blank">documentation</a>.</p>
<pre><code class="language-java">// including showing and not-showing components in component lookups
Robot robot = BasicRobot.robotWithNewAwtHierarchy();
robot.settings().componentLookupScope(ComponentLookupScope.ALL);</code></pre>
<div class="panel panel-info">
<div class="panel-heading">Note</div>
<div class="panel-body">
This setting affects component <strong>lookup by name and type only</strong>. Creators of
implementations of <code>GenericTypeMatcher</code> need to specify if lookup includes non-showing
components or not.
</div>
</div>
<h4>Using a <code>ComponentFinder</code></h4>
<p>Although we recommend to look up GUI components using a <code>ContainerFixture</code>, you can also use a
<code>ComponentFinder</code>. It supports different types of component lookup (please find details in
its <a href="swing/api/org/assertj/swing/core/ComponentFinder.html" target="_blank">documentation</a>):</p>
<ul>
<li>by name</li>
<li>by type</li>
<li>by name and type</li>
<li>custom search criteria using a <code>ComponentMatcher</code></li>
<li>custom search criteria using a <code>GenericTypeMatcher</code></li>
</ul>
<h5>Obtaining a ComponentFinder</h5>
<p>There are three ways to obtain a ComponentFinder:</p>
<ol>
<li>By creating a new <code>ComponentFinder</code> that has access to all the GUI components in the AWT
hierarchy.
<pre><code class="language-java">ComponentFinder finder = BasicComponentFinder.finderWithCurrentAwtHierarchy();</code></pre>
</li>
<li>By creating a new <code>ComponentFinder</code> that only has access to the GUI components created after
it. In the following example, finder has access to <code>MainFrame</code> but not to <code>LoginFrame</code>.
<pre><code class="language-java">// new LoginFrame();
ComponentFinder finder = BasicComponentFinder.finderWithNewAwtHierarchy();
finder.findByName("login", true); // will fail finding component of login frame
// new MainFrame();
finder.findByName("pw", true); // will work finding label of main frame</code></pre>
</li>
<li>By reusing an existing <code>ComponentFinder</code> from a <code>Robot</code>. In the following
example we're going to use the <code>Robot</code> from the
<a href="assertj-swing-basics.html#base-test-case">base test class</a>:
<pre><code class="lanuage-java">ComponentFinder finder = robot().finder();</code></pre>
</li>
</ol>
<h3 class="page-header"><span id="long-duration"></span>Testing Long-Duration Tasks</h3>
<p>AssertJ Swing provides support for finding GUI components after the execution of a long-duration task
is complete. Currently, it provides the following finders (in the package
<code>org.assertj.swing.finder</code>):</p>
<ul>
<li><code><a href="swing/api/org/assertj/swing/finder/WindowFinder.html" target="_blank">WindowFinder</a></code>
(which can find instances of Frame and Dialog)</li>
<li><code><a href="swing/api/org/assertj/swing/finder/JOptionPaneFinder.html" target="_blank">JOptionPaneFinder</a></code></li>
<li><code><a href="swing/api/org/assertj/swing/finder/JFileChooserFinder.html" target="_blank">JFileChooserFinder</a></code></li>
</ul>
<p>A good example for a long running task is the login procedure of an application. The main window is being
shown after the user's credentials have been successfully verified. The following are the typical steps to
complete such scenario:</p>
<ol>
<li>User launches the application</li>
<li>A login window appears</li>
<li>User enters her username and password and clicks the <em>Login</em> button</li>
<li>User is authenticated and authorized successfully</li>
<li>The main window of the application is displayed</li>
</ol>
<p>The <em>tricky</em> part here is step 4. Authentication/authorization can take some time (depending on
network traffic, etc.) and we need to wait for the main window to appear in order to continue our test. It
is possible to test this scenario with AssertJ Swing:</p>
<h4>Lookup by name</h4>
<pre><code class="language-java">// import static org.assertj.swing.finder.WindowFinder.findFrame;
window.textBox("username").enterText("yvonne");
window.textBox("password").enterText("welcome");
window.button("login").click();
// now the interesting part, we need to wait till the main window is shown.
FrameFixture mainFrame = findFrame("main").using(robot());
// we can continue testing the main window.</code></pre>
<p>The <code>findFrame()</code> method (statically imported from <code>WindowFinder</code>) can look up a
Frame having <code>main</code> as its name with a default timeout of 5 seconds. This means that if in
5 seconds the frame we're looking for isn't found, the test will fail.</p>
<p>We can also specify a custom value for the timeout. For example, we can set the timeout to 10 seconds
in two ways:</p>
<pre><code class="language-java">// import static org.assertj.swing.finder.WindowFinder.findFrame;
// import static java.util.concurrent.TimeUnit.SECONDS;
FrameFixture mainFrame = findFrame("main").withTimeout(10000).using(robot());
// or
FrameFixture mainFrame = findFrame("main").withTimeout(10, SECONDS).using(robot());</code></pre>
<h4>Lookup by type</h4>
<p>We can also find components by type. In this example, we look up a showing a <code>Frame</code> of type
<code>MainFrame</code>, using the default timeout of 5 seconds.</p>
<pre><code class="language-java">// import static org.assertj.swing.finder.WindowFinder.findFrame;
FrameFixture mainFrame = findFrame(MainFrame.class).using(robot());</code></pre>
<h4>Lookup using a GenericTypeMatcher</h4>
<p>All finders accept a <code>GenericTypeMatcher</code> to find components using custom search criteria. In
the following example, we look up a showing frame whose title starts with <code>News</code>:</p>
<pre><code class="language-java">// import static org.assertj.swing.finder.WindowFinder.findFrame;
GenericTypeMatcher<JFrame> matcher = new GenericTypeMatcher<JFrame>(JFrame.class) {
protected boolean isMatching(JFrame frame) {
return frame.getTitle() != null && frame.getTitle().startsWith("News") && frame.isShowing();
}
};
FrameFixture frame = findFrame(matcher).using(robot());</code></pre>
<h4>Reusing Robots</h4>
<p>In the example above, we used the method call <code>using(loginDialog.robot)</code>. Although strange,
this is necessary because, in a given test, only one instance of <code>Robot</code> can be running, to
prevent GUI tests from blocking each other on the screen. In other words, in a test class you can only use
one and only one instance of Robot.</p>
</div>
</div>
</div>
<br>
<!--
<div class="container">
<footer>
<div class="row">
<div class="col-lg-12">
<p>AssertJ - Licensed under the Apache License, Version 2.0.</p>
</div>
</div>
</footer>
</div>
-->
<script src="js/jquery-1.10.2.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/modern-business.js"></script>
<script src="js/assertj.js"></script>
</body>
</html>