OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef CHROME_TEST_UI_UI_TEST_H_ | |
6 #define CHROME_TEST_UI_UI_TEST_H_ | |
7 | |
8 // This file provides a common base for running UI unit tests, which operate | |
9 // the entire browser application in a separate process for holistic | |
10 // functional testing. | |
11 // | |
12 // Tests should #include this file, subclass UITest, and use the TEST_F macro | |
13 // to declare individual test cases. This provides a running browser window | |
14 // during the test, accessible through the window_ member variable. The window | |
15 // will close when the test ends, regardless of whether the test passed. | |
16 // | |
17 // Tests which need to launch the browser with a particular set of command-line | |
18 // arguments should set the value of launch_arguments_ in their constructors. | |
19 | |
20 #include <string> | |
21 | |
22 #include "base/command_line.h" | |
23 #include "base/memory/scoped_ptr.h" | |
24 #include "base/message_loop/message_loop.h" | |
25 #include "base/process/process.h" | |
26 #include "base/time/time.h" | |
27 #include "chrome/test/automation/proxy_launcher.h" | |
28 #include "testing/platform_test.h" | |
29 #include "url/gurl.h" | |
30 | |
31 class AutomationProxy; | |
32 class BrowserProxy; | |
33 class GURL; | |
34 class TabProxy; | |
35 | |
36 namespace base { | |
37 class DictionaryValue; | |
38 class FilePath; | |
39 } | |
40 | |
41 // Base class for UI Tests. This implements the core of the functions. | |
42 // This base class decouples all automation functionality from testing | |
43 // infrastructure, for use without gtest. | |
44 // If using gtest, you probably want to inherit from UITest (declared below) | |
45 // rather than UITestBase. | |
46 class UITestBase { | |
47 public: | |
48 // ********* Utility functions ********* | |
49 | |
50 // Launches the browser only. | |
51 void LaunchBrowser(); | |
52 | |
53 // Launches the browser and IPC testing connection in server mode. | |
54 void LaunchBrowserAndServer(); | |
55 | |
56 // Launches the IPC testing connection in client mode, | |
57 // which then attempts to connect to a browser. | |
58 void ConnectToRunningBrowser(); | |
59 | |
60 // Only for pyauto. | |
61 base::TimeDelta action_timeout(); | |
62 int action_timeout_ms(); | |
63 void set_action_timeout(base::TimeDelta timeout); | |
64 void set_action_timeout_ms(int timeout); | |
65 | |
66 // Overridable so that derived classes can provide their own ProxyLauncher. | |
67 virtual ProxyLauncher* CreateProxyLauncher(); | |
68 | |
69 // Closes the browser and IPC testing server. | |
70 void CloseBrowserAndServer(); | |
71 | |
72 // Launches the browser with the given command line. | |
73 // TODO(phajdan.jr): Make LaunchBrowser private. | |
74 void LaunchBrowser(const base::CommandLine& cmdline, bool clear_profile); | |
75 | |
76 // Exits out browser instance. | |
77 void QuitBrowser(); | |
78 | |
79 // Tells the browser to navigate to the given URL in the active tab | |
80 // of the first app window. | |
81 // This method doesn't return until the navigation is complete. | |
82 void NavigateToURL(const GURL& url); | |
83 | |
84 // Navigate to the given URL in the active tab of the given app window. | |
85 void NavigateToURL(const GURL& url, int window_index); | |
86 | |
87 // Same as above, except in the given tab and window. | |
88 void NavigateToURL(const GURL& url, int window_index, int tab_index); | |
89 | |
90 // Tells the browser to navigate to the given URL in the active tab | |
91 // of the first app window. | |
92 // This method doesn't return until the |number_of_navigations| navigations | |
93 // complete. | |
94 void NavigateToURLBlockUntilNavigationsComplete(const GURL& url, | |
95 int number_of_navigations); | |
96 | |
97 // Same as above, except in the given tab and window. | |
98 void NavigateToURLBlockUntilNavigationsComplete(const GURL& url, | |
99 int number_of_navigations, int tab_index, int window_index); | |
100 | |
101 // Returns the URL of the currently active tab. Only looks in the first | |
102 // window, for backward compatibility. If there is no active tab, or some | |
103 // other error, the returned URL will be empty. | |
104 GURL GetActiveTabURL() { return GetActiveTabURL(0); } | |
105 | |
106 // Like above, but looks at the window at the given index. | |
107 GURL GetActiveTabURL(int window_index); | |
108 | |
109 // Returns the title of the currently active tab. Only looks in the first | |
110 // window, for backward compatibility. | |
111 std::wstring GetActiveTabTitle() { return GetActiveTabTitle(0); } | |
112 | |
113 // Like above, but looks at the window at the given index. | |
114 std::wstring GetActiveTabTitle(int window_index); | |
115 | |
116 // Returns the tabstrip index of the currently active tab in the window at | |
117 // the given index, or -1 on error. Only looks in the first window, for | |
118 // backward compatibility. | |
119 int GetActiveTabIndex() { return GetActiveTabIndex(0); } | |
120 | |
121 // Like above, but looks at the window at the given index. | |
122 int GetActiveTabIndex(int window_index); | |
123 | |
124 // Returns the number of tabs in the first window. If no windows exist, | |
125 // causes a test failure and returns 0. | |
126 int GetTabCount(); | |
127 | |
128 // Same as GetTabCount(), except with the window at the given index. | |
129 int GetTabCount(int window_index); | |
130 | |
131 // Polls up to kWaitForActionMaxMsec ms to attain a specific tab count. Will | |
132 // assert that the tab count is valid at the end of the wait. | |
133 void WaitUntilTabCount(int tab_count); | |
134 | |
135 // Closes the specified browser. Returns true if the browser was closed. | |
136 // This call is blocking. |application_closed| is set to true if this was | |
137 // the last browser window (and therefore as a result of it closing the | |
138 // browser process terminated). Note that in that case this method returns | |
139 // after the browser process has terminated. | |
140 bool CloseBrowser(BrowserProxy* browser, bool* application_closed) const; | |
141 | |
142 // Gets the executable file path of the Chrome browser process. | |
143 const base::FilePath::CharType* GetExecutablePath(); | |
144 | |
145 // Return the user data directory being used by the browser instance in | |
146 // UITest::SetUp(). | |
147 base::FilePath user_data_dir() const { | |
148 return launcher_->user_data_dir(); | |
149 } | |
150 | |
151 // Called by some tests that wish to have a base profile to start from. This | |
152 // "user data directory" (containing one or more profiles) will be recursively | |
153 // copied into the user data directory for the test and the files will be | |
154 // evicted from the OS cache. To start with a blank profile, supply an empty | |
155 // string (the default). | |
156 const base::FilePath& template_user_data() const { return template_user_data_;
} | |
157 void set_template_user_data(const base::FilePath& template_user_data) { | |
158 template_user_data_ = template_user_data; | |
159 } | |
160 | |
161 // Get the handle of browser process connected to the automation. This | |
162 // function only returns a reference to the handle so the caller does not | |
163 // own the handle returned. | |
164 base::ProcessHandle process() const { return launcher_->process(); } | |
165 | |
166 // Return the process id of the browser process (-1 on error). | |
167 base::ProcessId browser_process_id() const { return launcher_->process_id(); } | |
168 | |
169 // Return the time when the browser was run. | |
170 base::TimeTicks browser_launch_time() const { | |
171 return launcher_->browser_launch_time(); | |
172 } | |
173 | |
174 // Return how long the shutdown took. | |
175 base::TimeDelta browser_quit_time() const { | |
176 return launcher_->browser_quit_time(); | |
177 } | |
178 | |
179 // Fetch the state which determines whether the profile will be cleared on | |
180 // next startup. | |
181 bool get_clear_profile() const { | |
182 return clear_profile_; | |
183 } | |
184 // Sets clear_profile_. Should be called before launching browser to have | |
185 // any effect. | |
186 void set_clear_profile(bool clear_profile) { | |
187 clear_profile_ = clear_profile; | |
188 } | |
189 | |
190 // homepage_ accessor. | |
191 std::string homepage() { | |
192 return homepage_; | |
193 } | |
194 | |
195 // Sets homepage_. Should be called before launching browser to have | |
196 // any effect. | |
197 void set_homepage(const std::string& homepage) { | |
198 homepage_ = homepage; | |
199 } | |
200 | |
201 void set_test_name(const std::string& name) { | |
202 test_name_ = name; | |
203 } | |
204 | |
205 // Sets the shutdown type, which defaults to WINDOW_CLOSE. | |
206 void set_shutdown_type(ProxyLauncher::ShutdownType value) { | |
207 launcher_->set_shutdown_type(value); | |
208 } | |
209 | |
210 // Get the number of crash dumps we've logged since the test started. | |
211 int GetCrashCount() const; | |
212 | |
213 // Returns empty string if there were no unexpected Chrome asserts or crashes, | |
214 // a string describing the failures otherwise. As a side effect, it will fail | |
215 // with EXPECT_EQ macros if this code runs within a gtest harness. | |
216 std::string CheckErrorsAndCrashes() const; | |
217 | |
218 // Use Chromium binaries from the given directory. | |
219 void SetBrowserDirectory(const base::FilePath& dir); | |
220 | |
221 // Appends a command-line switch (no associated value) to be passed to the | |
222 // browser when launched. | |
223 void AppendBrowserLaunchSwitch(const char* name); | |
224 | |
225 // Appends a command-line switch with associated value to be passed to the | |
226 // browser when launched. | |
227 void AppendBrowserLaunchSwitch(const char* name, const char* value); | |
228 | |
229 // Pass-through to AutomationProxy::BeginTracing. | |
230 bool BeginTracing(const std::string& category_patterns); | |
231 | |
232 // Pass-through to AutomationProxy::EndTracing. | |
233 std::string EndTracing(); | |
234 | |
235 protected: | |
236 // String to display when a test fails because the crash service isn't | |
237 // running. | |
238 static const wchar_t kFailedNoCrashService[]; | |
239 | |
240 UITestBase(); | |
241 explicit UITestBase(base::MessageLoop::Type msg_loop_type); | |
242 | |
243 virtual ~UITestBase(); | |
244 | |
245 // Starts the browser using the arguments in launch_arguments_, and | |
246 // sets up member variables. | |
247 virtual void SetUp(); | |
248 | |
249 // Closes the browser window. | |
250 virtual void TearDown(); | |
251 | |
252 virtual AutomationProxy* automation() const; | |
253 | |
254 ProxyLauncher::LaunchState DefaultLaunchState(); | |
255 | |
256 // Extra command-line switches that need to be passed to the browser are | |
257 // added in this function. Add new command-line switches here. | |
258 virtual void SetLaunchSwitches(); | |
259 | |
260 // Called by the ProxyLauncher just before the browser is launched, allowing | |
261 // setup of the profile for the runtime environment.. | |
262 virtual void SetUpProfile(); | |
263 | |
264 // Returns the proxy for the currently active tab, or NULL if there is no | |
265 // tab or there was some kind of error. Only looks at the first window, for | |
266 // backward compatibility. The returned pointer MUST be deleted by the | |
267 // caller if non-NULL. | |
268 scoped_refptr<TabProxy> GetActiveTab(); | |
269 | |
270 // Like above, but looks at the window at the given index. | |
271 scoped_refptr<TabProxy> GetActiveTab(int window_index); | |
272 | |
273 // ********* Member variables ********* | |
274 | |
275 // Path to the browser executable. | |
276 base::FilePath browser_directory_; | |
277 | |
278 // Path to the unit test data. | |
279 base::FilePath test_data_directory_; | |
280 | |
281 // Command to launch the browser | |
282 base::CommandLine launch_arguments_; | |
283 | |
284 // The number of errors expected during the run (generally 0). | |
285 size_t expected_errors_; | |
286 | |
287 // The number of crashes expected during the run (generally 0). | |
288 int expected_crashes_; | |
289 | |
290 // Homepage used for testing. | |
291 std::string homepage_; | |
292 | |
293 // Name of currently running automated test passed to Chrome process. | |
294 std::string test_name_; | |
295 | |
296 // Wait for initial loads to complete in SetUp() before running test body. | |
297 bool wait_for_initial_loads_; | |
298 | |
299 // This can be set to true to have the test run the dom automation case. | |
300 bool dom_automation_enabled_; | |
301 | |
302 // This can be set to true to enable the stats collection controller JS | |
303 // bindings. | |
304 bool stats_collection_controller_enabled_; | |
305 | |
306 // See set_template_user_data(). | |
307 base::FilePath template_user_data_; | |
308 | |
309 // Determines if the window is shown or hidden. Defaults to hidden. | |
310 bool show_window_; | |
311 | |
312 // If true the profile is cleared before launching. Default is true. | |
313 bool clear_profile_; | |
314 | |
315 // Should we supply the testing channel id | |
316 // on the command line? Default is true. | |
317 bool include_testing_id_; | |
318 | |
319 // Enable file cookies, default is true. | |
320 bool enable_file_cookies_; | |
321 | |
322 // Launches browser and AutomationProxy. | |
323 scoped_ptr<ProxyLauncher> launcher_; | |
324 | |
325 // PID file for websocket server. | |
326 base::FilePath websocket_pid_file_; | |
327 | |
328 private: | |
329 // Time the test was started (so we can check for new crash dumps) | |
330 base::Time test_start_time_; | |
331 }; | |
332 | |
333 class UITest : public UITestBase, public PlatformTest { | |
334 protected: | |
335 UITest() {} | |
336 explicit UITest(base::MessageLoop::Type msg_loop_type) | |
337 : UITestBase(), PlatformTest(), message_loop_(msg_loop_type) {} | |
338 | |
339 virtual void SetUp() OVERRIDE; | |
340 virtual void TearDown() OVERRIDE; | |
341 | |
342 virtual ProxyLauncher* CreateProxyLauncher() OVERRIDE; | |
343 | |
344 // Count the number of active browser processes launched by this test. | |
345 // The count includes browser sub-processes. | |
346 bool GetBrowserProcessCount(int* count) WARN_UNUSED_RESULT; | |
347 | |
348 // Returns a copy of local state preferences. The caller is responsible for | |
349 // deleting the returned object. Returns NULL if there is an error. | |
350 base::DictionaryValue* GetLocalState(); | |
351 | |
352 // Returns a copy of the default profile preferences. The caller is | |
353 // responsible for deleting the returned object. Returns NULL if there is an | |
354 // error. | |
355 base::DictionaryValue* GetDefaultProfilePreferences(); | |
356 | |
357 // Waits for the test case to finish. | |
358 // ASSERTS if there are test failures. | |
359 void WaitForFinish(const std::string &name, | |
360 const std::string &id, const GURL &url, | |
361 const std::string& test_complete_cookie, | |
362 const std::string& expected_cookie_value, | |
363 const base::TimeDelta wait_time); | |
364 | |
365 // Polls the tab for a JavaScript condition and returns once one of the | |
366 // following conditions hold true: | |
367 // - The JavaScript condition evaluates to true (return true). | |
368 // - The browser process died (return false). | |
369 // - The timeout value has been exceeded (return false). | |
370 // | |
371 // The JavaScript expression is executed in the context of the frame that | |
372 // matches the provided xpath. | |
373 bool WaitUntilJavaScriptCondition(TabProxy* tab, | |
374 const std::wstring& frame_xpath, | |
375 const std::wstring& jscript, | |
376 base::TimeDelta timeout); | |
377 | |
378 // Polls the tab for the cookie_name cookie and returns once one of the | |
379 // following conditions hold true: | |
380 // - The cookie is of expected_value. | |
381 // - The browser process died. | |
382 // - The timeout value has been exceeded. | |
383 bool WaitUntilCookieValue(TabProxy* tab, const GURL& url, | |
384 const char* cookie_name, | |
385 base::TimeDelta timeout, | |
386 const char* expected_value); | |
387 | |
388 // Polls the tab for the cookie_name cookie and returns once one of the | |
389 // following conditions hold true: | |
390 // - The cookie is set to any value. | |
391 // - The browser process died. | |
392 // - The timeout value has been exceeded. | |
393 std::string WaitUntilCookieNonEmpty(TabProxy* tab, | |
394 const GURL& url, | |
395 const char* cookie_name, | |
396 base::TimeDelta timeout); | |
397 | |
398 // Waits until the Find window has become fully visible (if |wait_for_open| is | |
399 // true) or fully hidden (if |wait_for_open| is false). This function can time | |
400 // out (return false) if the window doesn't appear within a specific time. | |
401 bool WaitForFindWindowVisibilityChange(BrowserProxy* browser, | |
402 bool wait_for_open); | |
403 | |
404 // Terminates the browser, simulates end of session. | |
405 void TerminateBrowser(); | |
406 | |
407 // Tells the browser to navigate to the given URL in the active tab | |
408 // of the first app window. | |
409 // Does not wait for the navigation to complete to return. | |
410 // To avoid intermittent test failures, use NavigateToURL instead, if | |
411 // possible. | |
412 void NavigateToURLAsync(const GURL& url); | |
413 | |
414 private: | |
415 base::MessageLoop message_loop_; // Enables PostTask to main thread. | |
416 }; | |
417 | |
418 // These exist only to support the gTest assertion macros, and | |
419 // shouldn't be used in normal program code. | |
420 #ifdef UNIT_TEST | |
421 std::ostream& operator<<(std::ostream& out, const std::wstring& wstr); | |
422 | |
423 template<typename T> | |
424 std::ostream& operator<<(std::ostream& out, const ::scoped_ptr<T>& ptr) { | |
425 return out << ptr.get(); | |
426 } | |
427 #endif // UNIT_TEST | |
428 | |
429 #endif // CHROME_TEST_UI_UI_TEST_H_ | |
OLD | NEW |