diff options
author | nirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-21 23:23:12 +0000 |
---|---|---|
committer | nirnimesh@chromium.org <nirnimesh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-21 23:23:12 +0000 |
commit | c5647608aaf50455dc0b41b8e9f03e597589d76c (patch) | |
tree | c4ab2e971161e92188b1b8543a4d859c76586f52 | |
parent | 9e42ad6261487d76b9336d7417361ee9de515adc (diff) | |
download | chromium_src-c5647608aaf50455dc0b41b8e9f03e597589d76c.zip chromium_src-c5647608aaf50455dc0b41b8e9f03e597589d76c.tar.gz chromium_src-c5647608aaf50455dc0b41b8e9f03e597589d76c.tar.bz2 |
PyAuto: Python Interface to Chromium's Automation Proxy.
PyAuto is a python interface to chromium's automation framework. It exposes
some of the Automation Proxy functions in Python. This can be used to play
around with chromium, or automate functional tests.
SWIG is used to bridge Automation Proxy's C++ to Python.
This CL addresses Mac-only to begin with. I'll be adding win/linux shortly.
Also, this CL breaks down UITest class into parts that does not use gtest
(UITestBase) and parts that does (UITest). UITestBase is used by pyauto.
BUG=32283
TEST=None
Review URL: http://codereview.chromium.org/555022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36808 0039d316-1c4b-4281-b951-d872f2087c98
-rwxr-xr-x | chrome/chrome_tests.gypi | 85 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyauto.py | 74 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyautolib.cc | 74 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyautolib.h | 54 | ||||
-rw-r--r-- | chrome/test/pyautolib/pyautolib.i | 63 | ||||
-rw-r--r-- | chrome/test/ui/ui_test.cc | 205 | ||||
-rw-r--r-- | chrome/test/ui/ui_test.h | 21 |
7 files changed, 479 insertions, 97 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 178d5f9..96726e4 100755 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1778,6 +1778,91 @@ }, ]}, # 'targets' ], # OS=="win" + ['OS=="mac"', { + 'targets': [ + # TODO(nirnimesh): enable for linux,win - crbug.com/32285 + { + # Documentation: http://dev.chromium.org/developers/pyauto + 'target_name': 'pyautolib', + 'type': 'shared_library', + 'dependencies': [ + 'chrome', + 'test_support_common', + 'chrome_resources', + 'chrome_strings', + 'theme_resources', + '../skia/skia.gyp:skia', + '../testing/gtest.gyp:gtest', + ], + 'export_dependent_settings': [ + 'test_support_common', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'test/pyautolib/pyautolib.cc', + 'test/pyautolib/pyautolib.h', + '<(INTERMEDIATE_DIR)/pyautolib_wrap.cc', + 'test/ui/ui_test.cc', + 'test/ui/ui_test.h', + 'test/ui/ui_test_suite.cc', + 'test/ui/ui_test_suite.h', + ], + # Need a shared object named _pyautolib.so (not libpyautolib.dylib + # that xcode would generate) + # Change when gyp can support a platform-neutral way for this + # (http://code.google.com/p/gyp/issues/detail?id=135) + 'xcode_settings': { + 'EXECUTABLE_PREFIX': '_', + 'EXECUTABLE_EXTENSION': 'so', + }, + 'conditions': [ + ['OS=="linux"', { + 'include_dirs': [ + '..', + '/usr/include/python2.5', + ], + 'dependencies': [ + '../build/linux/system.gyp:gtk', + ], + }], + ['OS=="mac"', { + 'include_dirs': [ + '..', + '$(SDKROOT)/usr/include/python2.5', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/usr/lib/libpython2.5.dylib', + ], + } + }], + ], + 'actions': [ + { + 'action_name': 'pyautolib_swig', + 'inputs': [ + 'test/pyautolib/pyautolib.i', + ], + 'outputs': [ + '<(INTERMEDIATE_DIR)/pyautolib_wrap.cc', + '<(PRODUCT_DIR)/pyautolib.py', + ], + 'action': [ 'swig', + '-python', + '-c++', + '-outdir', + '<(PRODUCT_DIR)', + '-o', + '<(INTERMEDIATE_DIR)/pyautolib_wrap.cc', + '<(_inputs)', + ] + }, + ], # actions + }, # target 'pyautolib' + ] # targets + }], # OS=='mac' ['coverage!=0', { 'targets': [ { diff --git a/chrome/test/pyautolib/pyauto.py b/chrome/test/pyautolib/pyauto.py new file mode 100644 index 0000000..66abdc9 --- /dev/null +++ b/chrome/test/pyautolib/pyauto.py @@ -0,0 +1,74 @@ +#!/usr/bin/python + +# Copyright (c) 2010 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""PyAuto: Python Interface to Chromium's Automation Proxy. + +PyAuto uses swig to expose Automation Proxy interfaces to Python. +For complete documentation on the functionality available, +run pydoc on this file. + +Ref: http://dev.chromium.org/developers/pyauto +""" + +import os +import sys +import unittest + + +def _LocateBinDirs(): + script_dir = os.path.dirname(__file__) + chrome_src = os.path.join(script_dir, os.pardir, os.pardir, os.pardir) + + # TODO(nirnimesh): Expand this to include win/linux build dirs + # crbug.com/32285 + bin_dirs = [ os.path.join(chrome_src, 'xcodebuild', 'Debug'), + os.path.join(chrome_src, 'xcodebuild', 'Release'), + ] + for d in bin_dirs: + sys.path.append(os.path.normpath(d)) + +_LocateBinDirs() + +try: + from pyautolib import PyUITestSuite +except ImportError: + print >>sys.stderr, "Could not locate built libraries. Did you build?" + raise + + +class PyUITest(PyUITestSuite, unittest.TestCase): + """Base class for UI Test Cases in Python. + + A browser is created before executing each test, and is destroyed after + each test irrespective of whether the test passed or failed. + + You should derive from this class and create methods with 'test' prefix, + and use methods inherited from PyUITestSuite (the C++ side). + + Example: + + class MyTest(PyUITest): + + def testNavigation(self): + self.NavigateToURL("http://www.google.com") + self.assertTrue("Google" == self.GetActiveTabTitle()) + """ + + def __init__(self, methodName='runTest'): + PyUITestSuite.__init__(self, sys.argv) + unittest.TestCase.__init__(self, methodName) + + def __del__(self): + PyUITestSuite.__del__(self) + + def run(self, result=None): + """The main run method. + + We override this method to make calls to the setup steps in PyUITestSuite. + """ + self.SetUp() # Open a browser window + unittest.TestCase.run(self, result) + self.TearDown() # Destroy the browser window diff --git a/chrome/test/pyautolib/pyautolib.cc b/chrome/test/pyautolib/pyautolib.cc new file mode 100644 index 0000000..a891e8e --- /dev/null +++ b/chrome/test/pyautolib/pyautolib.cc @@ -0,0 +1,74 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/scoped_ptr.h" +#include "chrome/test/automation/tab_proxy.h" +#include "chrome/test/pyautolib/pyautolib.h" +#include "googleurl/src/gurl.h" + +PyUITestSuite::PyUITestSuite(int argc, char** argv) + : UITestSuite(argc, argv), + UITestBase() { + UITestSuite::Initialize(); +} + +PyUITestSuite::~PyUITestSuite() { + UITestSuite::Shutdown(); +} + +void PyUITestSuite::SetUp() { + UITestBase::SetUp(); +} + +void PyUITestSuite::TearDown() { + UITestBase::TearDown(); +} + +void PyUITestSuite::NavigateToURL(const char* url_string) { + GURL url(url_string); + UITestBase::NavigateToURL(url); +} + +void PyUITestSuite::SetShelfVisible(bool is_visible) { + scoped_refptr<BrowserProxy> browser_proxy = automation()->GetBrowserWindow(0); + ASSERT_TRUE(browser_proxy.get()); + EXPECT_TRUE(browser_proxy->SetShelfVisible(is_visible)); +} + +bool PyUITestSuite::IsShelfVisible() { + scoped_refptr<BrowserProxy> browser_proxy = automation()->GetBrowserWindow(0); + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + bool visible = false; + EXPECT_TRUE(browser_proxy->IsShelfVisible(&visible)); + return visible; +} + +std::wstring PyUITestSuite::GetActiveTabTitle() { + std::wstring title; + scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); + EXPECT_TRUE(tab_proxy.get()); + if (!tab_proxy.get()) + return title; + EXPECT_TRUE(tab_proxy->GetTabTitle(&title)); + return title; +} + +void PyUITestSuite::OpenFindInPage() { + scoped_refptr<BrowserProxy> browser_proxy = automation()->GetBrowserWindow(0); + ASSERT_TRUE(browser_proxy.get()); + EXPECT_TRUE(browser_proxy->OpenFindInPage()); +} + +bool PyUITestSuite::IsFindInPageVisible() { + scoped_refptr<BrowserProxy> browser_proxy = automation()->GetBrowserWindow(0); + EXPECT_TRUE(browser_proxy.get()); + if (!browser_proxy.get()) + return false; + bool is_visible; + EXPECT_TRUE(browser_proxy->IsFindWindowFullyVisible(&is_visible)); + return is_visible; +} + diff --git a/chrome/test/pyautolib/pyautolib.h b/chrome/test/pyautolib/pyautolib.h new file mode 100644 index 0000000..04fe7a8 --- /dev/null +++ b/chrome/test/pyautolib/pyautolib.h @@ -0,0 +1,54 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This file declares the C++ side of PyAuto, the python interface to +// Chromium automation. It access Chromium's internals using Automation Proxy. + +#ifndef CHROME_TEST_PYAUTOLIB_PYAUTOLIB_H_ +#define CHROME_TEST_PYAUTOLIB_PYAUTOLIB_H_ + +#include "base/scoped_nsautorelease_pool.h" +#include "chrome/test/ui/ui_test.h" +#include "chrome/test/ui/ui_test_suite.h" + +// TODO(nirnimesh): separate out the UITestSuite and UITestBase parts +// crbug.com/32292 + +// The primary class that interfaces with Automation Proxy. +// This class is accessed from python using swig. +class PyUITestSuite : public UITestSuite, public UITestBase { + public: + // Only public methods are accessible from swig. + PyUITestSuite(int argc, char** argv); + ~PyUITestSuite(); + + // SetUp,TearDown is redeclared as public to make it accessible from swig. + virtual void SetUp(); + virtual void TearDown(); + + void NavigateToURL(const char* url_string); + + // Get the title of the active tab. Empty string in case of error. + std::wstring GetActiveTabTitle(); + + // BrowserProxy methods + + // Shows or hides the download shelf. + void SetShelfVisible(bool is_visible); + + // Determines the visibility of the download shelf + bool IsShelfVisible(); + + // Open the Find box + void OpenFindInPage(); + + // Determines the visibility of the Find box + bool IsFindInPageVisible(); + + private: + base::ScopedNSAutoreleasePool pool_; +}; + +#endif // CHROME_TEST_PYAUTOLIB_PYAUTOLIB_H_ + diff --git a/chrome/test/pyautolib/pyautolib.i b/chrome/test/pyautolib/pyautolib.i new file mode 100644 index 0000000..83854c0 --- /dev/null +++ b/chrome/test/pyautolib/pyautolib.i @@ -0,0 +1,63 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Swig Interface for PyAuto. +// PyAuto makes the Automation Proxy interface available in Python +// +// Running swig as: +// swig -python -c++ chrome/test/pyautolib/pyautolib.i +// would generate pyautolib.py, pyautolib_wrap.cxx + +%module pyautolib + +%include "std_string.i" +%include "std_wstring.i" + +%{ +#include "chrome/test/pyautolib/pyautolib.h" +%} + +// Make functions using (int argc, char** argv) usable as (sys.argv) from python +%typemap(in) (int argc, char **argv) { + int i; + if (!PyList_Check($input)) { + PyErr_SetString(PyExc_ValueError, "Expecting a list"); + return NULL; + } + $1 = PyList_Size($input); + $2 = (char **) malloc(($1+1)*sizeof(char *)); + for (i = 0; i < $1; i++) { + PyObject *s = PyList_GetItem($input,i); + if (!PyString_Check(s)) { + free($2); + PyErr_SetString(PyExc_ValueError, "List items must be strings"); + return NULL; + } + $2[i] = PyString_AsString(s); + } + $2[i] = 0; +} + +%typemap(freearg) (int argc, char **argv) { + if ($2) free($2); +} + + +// TODO(nirnimesh): Fill in the autodoc constructs - crbug.com/32287 +class PyUITestSuite { + public: + PyUITestSuite(int argc, char** argv); + + virtual void SetUp(); + virtual void TearDown(); + + void NavigateToURL(const char* url_string); + std::wstring GetActiveTabTitle(); + + // BrowserProxy methods + void SetShelfVisible(bool is_visible); + bool IsShelfVisible(); + void OpenFindInPage(); + bool IsFindInPageVisible(); +}; diff --git a/chrome/test/ui/ui_test.cc b/chrome/test/ui/ui_test.cc index 2eb163f..a462fb5 100644 --- a/chrome/test/ui/ui_test.cc +++ b/chrome/test/ui/ui_test.cc @@ -50,7 +50,7 @@ static const int kMaxTestExecutionTime = 30000; // Delay to let the browser shut down before trying more brutal methods. static const int kWaitForTerminateMsec = 30000; -const wchar_t UITest::kFailedNoCrashService[] = +const wchar_t UITestBase::kFailedNoCrashService[] = #if defined(OS_WIN) L"NOTE: This test is expected to fail if crash_service.exe is not " L"running. Start it manually before running this test (see the build " @@ -61,19 +61,19 @@ const wchar_t UITest::kFailedNoCrashService[] = #else L"NOTE: Crash service not ported to this platform!"; #endif -bool UITest::in_process_renderer_ = false; -bool UITest::no_sandbox_ = false; -bool UITest::full_memory_dump_ = false; -bool UITest::safe_plugins_ = false; -bool UITest::show_error_dialogs_ = true; -bool UITest::default_use_existing_browser_ = false; -bool UITest::dump_histograms_on_exit_ = false; -bool UITest::enable_dcheck_ = false; -bool UITest::silent_dump_on_dcheck_ = false; -bool UITest::disable_breakpad_ = false; -int UITest::timeout_ms_ = 20 * 60 * 1000; -std::wstring UITest::js_flags_ = L""; -std::wstring UITest::log_level_ = L""; +bool UITestBase::in_process_renderer_ = false; +bool UITestBase::no_sandbox_ = false; +bool UITestBase::full_memory_dump_ = false; +bool UITestBase::safe_plugins_ = false; +bool UITestBase::show_error_dialogs_ = true; +bool UITestBase::default_use_existing_browser_ = false; +bool UITestBase::dump_histograms_on_exit_ = false; +bool UITestBase::enable_dcheck_ = false; +bool UITestBase::silent_dump_on_dcheck_ = false; +bool UITestBase::disable_breakpad_ = false; +int UITestBase::timeout_ms_ = 20 * 60 * 1000; +std::wstring UITestBase::js_flags_ = L""; +std::wstring UITestBase::log_level_ = L""; // Specify the time (in milliseconds) that the ui_tests should wait before // timing out. This is used to specify longer timeouts when running under Purify @@ -95,9 +95,8 @@ const char kEnableErrorDialogs[] = "enable-errdialogs"; // BROWSER_WRAPPER env variable to wrap the browser process. // #define WAIT_FOR_DEBUGGER_ON_OPEN 1 -UITest::UITest() - : PlatformTest(), - launch_arguments_(CommandLine::ARGUMENTS_ONLY), +UITestBase::UITestBase() + : launch_arguments_(CommandLine::ARGUMENTS_ONLY), expected_errors_(0), expected_crashes_(0), homepage_(L"about:blank"), @@ -110,7 +109,7 @@ UITest::UITest() include_testing_id_(true), use_existing_browser_(default_use_existing_browser_), enable_file_cookies_(true), - profile_type_(UITest::DEFAULT_THEME), + profile_type_(UITestBase::DEFAULT_THEME), test_start_time_(base::Time::NowFromSystemTime()), command_execution_timeout_ms_(kMaxTestExecutionTime), action_timeout_ms_(kWaitForActionMsec), @@ -121,28 +120,20 @@ UITest::UITest() PathService::Get(chrome::DIR_TEST_DATA, &test_data_directory_); } -void UITest::SetUp() { +UITestBase::~UITestBase() { +} + +void UITestBase::SetUp() { if (!use_existing_browser_) { AssertAppNotRunning(L"Please close any other instances " L"of the app before testing."); } - // Pass the test case name to chrome.exe on the command line to help with - // parsing Purify output. - const testing::TestInfo* const test_info = - testing::UnitTest::GetInstance()->current_test_info(); - if (test_info) { - std::string test_name = test_info->test_case_name(); - test_name += "."; - test_name += test_info->name(); - ui_test_name_ = ASCIIToWide(test_name); - } - InitializeTimeouts(); LaunchBrowserAndServer(); } -void UITest::TearDown() { +void UITestBase::TearDown() { CloseBrowserAndServer(); // Make sure that we didn't encounter any assertion failures @@ -177,7 +168,7 @@ void UITest::TearDown() { } // Pick up the various test time out values from the command line. -void UITest::InitializeTimeouts() { +void UITestBase::InitializeTimeouts() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); if (command_line.HasSwitch(kUiTestTimeout)) { std::wstring timeout_str = command_line.GetSwitchValue(kUiTestTimeout); @@ -214,12 +205,12 @@ void UITest::InitializeTimeouts() { } } -AutomationProxy* UITest::CreateAutomationProxy(int execution_timeout) { +AutomationProxy* UITestBase::CreateAutomationProxy(int execution_timeout) { // By default we create a plain vanilla AutomationProxy. return new AutomationProxy(execution_timeout); } -void UITest::LaunchBrowserAndServer() { +void UITestBase::LaunchBrowserAndServer() { // Set up IPC testing interface server. server_.reset(CreateAutomationProxy(command_execution_timeout_ms_)); @@ -233,7 +224,7 @@ void UITest::LaunchBrowserAndServer() { automation()->SetFilteredInet(ShouldFilterInet()); } -void UITest::CloseBrowserAndServer() { +void UITestBase::CloseBrowserAndServer() { QuitBrowser(); CleanupAppProcesses(); @@ -323,11 +314,11 @@ static void RunCommand(const CommandLine& cmd_line) { #endif } -void UITest::StartHttpServer(const FilePath& root_directory) { +void UITestBase::StartHttpServer(const FilePath& root_directory) { StartHttpServerWithPort(root_directory, L""); } -void UITest::StartHttpServerWithPort(const FilePath& root_directory, +void UITestBase::StartHttpServerWithPort(const FilePath& root_directory, const std::wstring& port) { scoped_ptr<CommandLine> cmd_line(CreateHttpServerCommandLine()); ASSERT_TRUE(cmd_line.get()); @@ -349,14 +340,14 @@ void UITest::StartHttpServerWithPort(const FilePath& root_directory, RunCommand(*cmd_line.get()); } -void UITest::StopHttpServer() { +void UITestBase::StopHttpServer() { scoped_ptr<CommandLine> cmd_line(CreateHttpServerCommandLine()); ASSERT_TRUE(cmd_line.get()); cmd_line->AppendSwitchWithValue("server", "stop"); RunCommand(*cmd_line.get()); } -void UITest::StartWebSocketServer(const FilePath& root_directory) { +void UITestBase::StartWebSocketServer(const FilePath& root_directory) { scoped_ptr<CommandLine> cmd_line(CreateWebSocketServerCommandLine()); ASSERT_TRUE(cmd_line.get()); cmd_line->AppendSwitchWithValue("server", "start"); @@ -369,7 +360,7 @@ void UITest::StartWebSocketServer(const FilePath& root_directory) { RunCommand(*cmd_line.get()); } -void UITest::StopWebSocketServer() { +void UITestBase::StopWebSocketServer() { scoped_ptr<CommandLine> cmd_line(CreateWebSocketServerCommandLine()); ASSERT_TRUE(cmd_line.get()); cmd_line->AppendSwitchWithValue("server", "stop"); @@ -378,7 +369,8 @@ void UITest::StopWebSocketServer() { RunCommand(*cmd_line.get()); } -void UITest::LaunchBrowser(const CommandLine& arguments, bool clear_profile) { +void UITestBase::LaunchBrowser(const CommandLine& arguments, + bool clear_profile) { #if defined(OS_POSIX) const char* alternative_userdir = getenv("CHROME_UI_TESTS_USER_DATA_DIR"); #else @@ -408,7 +400,7 @@ void UITest::LaunchBrowser(const CommandLine& arguments, bool clear_profile) { user_data_dir_)); // If we're using the complex theme data, we need to write the // user_data_dir_ to our preferences file. - if (profile_type_ == UITest::COMPLEX_THEME) { + if (profile_type_ == UITestBase::COMPLEX_THEME) { RewritePreferencesFile(user_data_dir_); } @@ -421,11 +413,12 @@ void UITest::LaunchBrowser(const CommandLine& arguments, bool clear_profile) { process_id_ = base::GetProcId(process_); } -bool UITest::LaunchAnotherBrowserBlockUntilClosed(const CommandLine& cmdline) { +bool UITestBase::LaunchAnotherBrowserBlockUntilClosed( + const CommandLine& cmdline) { return LaunchBrowserHelper(cmdline, false, true, NULL); } -void UITest::QuitBrowser() { +void UITestBase::QuitBrowser() { // There's nothing to do here if the browser is not running. if (IsBrowserRunning()) { automation()->SetFilteredInet(false); @@ -475,7 +468,7 @@ void UITest::QuitBrowser() { process_id_ = -1; } -void UITest::AssertAppNotRunning(const std::wstring& error_message) { +void UITestBase::AssertAppNotRunning(const std::wstring& error_message) { std::wstring final_error_message(error_message); ChromeProcessList processes = GetRunningChromeProcesses(process_id_); @@ -490,11 +483,11 @@ void UITest::AssertAppNotRunning(const std::wstring& error_message) { ASSERT_TRUE(processes.empty()) << final_error_message; } -void UITest::CleanupAppProcesses() { +void UITestBase::CleanupAppProcesses() { TerminateAllChromeProcesses(process_id_); } -scoped_refptr<TabProxy> UITest::GetActiveTab(int window_index) { +scoped_refptr<TabProxy> UITestBase::GetActiveTab(int window_index) { EXPECT_GE(window_index, 0); int window_count = -1; // We have to use EXPECT rather than ASSERT here because ASSERT_* only works @@ -516,7 +509,7 @@ scoped_refptr<TabProxy> UITest::GetActiveTab(int window_index) { return window_proxy->GetTab(active_tab_index); } -scoped_refptr<TabProxy> UITest::GetActiveTab() { +scoped_refptr<TabProxy> UITestBase::GetActiveTab() { scoped_refptr<BrowserProxy> window_proxy(automation()-> GetBrowserWindow(0)); EXPECT_TRUE(window_proxy.get()); @@ -528,7 +521,7 @@ scoped_refptr<TabProxy> UITest::GetActiveTab() { return tab_proxy; } -void UITest::NavigateToURLAsync(const GURL& url) { +void UITestBase::NavigateToURLAsync(const GURL& url) { scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); ASSERT_TRUE(tab_proxy.get()); if (!tab_proxy.get()) @@ -537,11 +530,11 @@ void UITest::NavigateToURLAsync(const GURL& url) { tab_proxy->NavigateToURLAsync(url); } -void UITest::NavigateToURL(const GURL& url) { +void UITestBase::NavigateToURL(const GURL& url) { NavigateToURLBlockUntilNavigationsComplete(url, 1); } -void UITest::NavigateToURLBlockUntilNavigationsComplete( +void UITestBase::NavigateToURLBlockUntilNavigationsComplete( const GURL& url, int number_of_navigations) { scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); ASSERT_TRUE(tab_proxy.get()); @@ -555,15 +548,15 @@ void UITest::NavigateToURLBlockUntilNavigationsComplete( ASSERT_FALSE(is_timeout) << url.spec(); } -bool UITest::WaitForDownloadShelfVisible(BrowserProxy* browser) { +bool UITestBase::WaitForDownloadShelfVisible(BrowserProxy* browser) { return WaitForDownloadShelfVisibilityChange(browser, true); } -bool UITest::WaitForDownloadShelfInvisible(BrowserProxy* browser) { +bool UITestBase::WaitForDownloadShelfInvisible(BrowserProxy* browser) { return WaitForDownloadShelfVisibilityChange(browser, false); } -bool UITest::WaitForDownloadShelfVisibilityChange(BrowserProxy* browser, +bool UITestBase::WaitForDownloadShelfVisibilityChange(BrowserProxy* browser, bool wait_for_open) { const int kCycles = 10; for (int i = 0; i < kCycles; i++) { @@ -579,7 +572,7 @@ bool UITest::WaitForDownloadShelfVisibilityChange(BrowserProxy* browser, return false; } -bool UITest::WaitForFindWindowVisibilityChange(BrowserProxy* browser, +bool UITestBase::WaitForFindWindowVisibilityChange(BrowserProxy* browser, bool wait_for_open) { const int kCycles = 10; for (int i = 0; i < kCycles; i++) { @@ -595,7 +588,7 @@ bool UITest::WaitForFindWindowVisibilityChange(BrowserProxy* browser, return false; } -bool UITest::WaitForBookmarkBarVisibilityChange(BrowserProxy* browser, +bool UITestBase::WaitForBookmarkBarVisibilityChange(BrowserProxy* browser, bool wait_for_open) { const int kCycles = 10; for (int i = 0; i < kCycles; i++) { @@ -612,7 +605,7 @@ bool UITest::WaitForBookmarkBarVisibilityChange(BrowserProxy* browser, return false; } -GURL UITest::GetActiveTabURL(int window_index) { +GURL UITestBase::GetActiveTabURL(int window_index) { scoped_refptr<TabProxy> tab_proxy(GetActiveTab(window_index)); EXPECT_TRUE(tab_proxy.get()); if (!tab_proxy.get()) @@ -626,7 +619,7 @@ GURL UITest::GetActiveTabURL(int window_index) { return url; } -std::wstring UITest::GetActiveTabTitle(int window_index) { +std::wstring UITestBase::GetActiveTabTitle(int window_index) { std::wstring title; scoped_refptr<TabProxy> tab_proxy(GetActiveTab(window_index)); EXPECT_TRUE(tab_proxy.get()); @@ -637,7 +630,7 @@ std::wstring UITest::GetActiveTabTitle(int window_index) { return title; } -int UITest::GetActiveTabIndex(int window_index) { +int UITestBase::GetActiveTabIndex(int window_index) { scoped_refptr<BrowserProxy> window_proxy(automation()-> GetBrowserWindow(window_index)); EXPECT_TRUE(window_proxy.get()); @@ -649,15 +642,15 @@ int UITest::GetActiveTabIndex(int window_index) { return active_tab_index; } -bool UITest::IsBrowserRunning() { +bool UITestBase::IsBrowserRunning() { return CrashAwareSleep(0); } -bool UITest::CrashAwareSleep(int time_out_ms) { +bool UITestBase::CrashAwareSleep(int time_out_ms) { return base::CrashAwareSleep(process_, time_out_ms); } -int UITest::GetBrowserProcessCount() { +int UITestBase::GetBrowserProcessCount() { return GetRunningChromeProcesses(process_id_).size(); } @@ -673,20 +666,20 @@ static DictionaryValue* LoadDictionaryValueFromPath(const FilePath& path) { return static_cast<DictionaryValue*>(root_value.release()); } -DictionaryValue* UITest::GetLocalState() { +DictionaryValue* UITestBase::GetLocalState() { FilePath local_state_path; PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); return LoadDictionaryValueFromPath(local_state_path); } -DictionaryValue* UITest::GetDefaultProfilePreferences() { +DictionaryValue* UITestBase::GetDefaultProfilePreferences() { FilePath path; PathService::Get(chrome::DIR_USER_DATA, &path); path = path.AppendASCII(WideToASCII(chrome::kNotSignedInProfile)); return LoadDictionaryValueFromPath(path.Append(chrome::kPreferencesFilename)); } -int UITest::GetTabCount() { +int UITestBase::GetTabCount() { scoped_refptr<BrowserProxy> first_window(automation()->GetBrowserWindow(0)); if (!first_window.get()) return 0; @@ -697,7 +690,7 @@ int UITest::GetTabCount() { return result; } -bool UITest::WaitUntilCookieValue(TabProxy* tab, +bool UITestBase::WaitUntilCookieValue(TabProxy* tab, const GURL& url, const char* cookie_name, int interval_ms, @@ -725,7 +718,7 @@ bool UITest::WaitUntilCookieValue(TabProxy* tab, return completed; } -std::string UITest::WaitUntilCookieNonEmpty(TabProxy* tab, +std::string UITestBase::WaitUntilCookieNonEmpty(TabProxy* tab, const GURL& url, const char* cookie_name, int interval_ms, @@ -751,7 +744,7 @@ std::string UITest::WaitUntilCookieNonEmpty(TabProxy* tab, return cookie_value; } -bool UITest::WaitUntilJavaScriptCondition(TabProxy* tab, +bool UITestBase::WaitUntilJavaScriptCondition(TabProxy* tab, const std::wstring& frame_xpath, const std::wstring& jscript, int interval_ms, @@ -781,7 +774,7 @@ bool UITest::WaitUntilJavaScriptCondition(TabProxy* tab, return completed; } -void UITest::WaitUntilTabCount(int tab_count) { +void UITestBase::WaitUntilTabCount(int tab_count) { for (int i = 0; i < 10; ++i) { PlatformThread::Sleep(sleep_timeout_ms() / 10); if (GetTabCount() == tab_count) @@ -790,7 +783,7 @@ void UITest::WaitUntilTabCount(int tab_count) { EXPECT_EQ(tab_count, GetTabCount()); } -FilePath UITest::GetDownloadDirectory() { +FilePath UITestBase::GetDownloadDirectory() { scoped_refptr<TabProxy> tab_proxy(GetActiveTab()); EXPECT_TRUE(tab_proxy.get()); if (!tab_proxy.get()) @@ -801,12 +794,12 @@ FilePath UITest::GetDownloadDirectory() { return download_directory; } -void UITest::CloseBrowserAsync(BrowserProxy* browser) const { +void UITestBase::CloseBrowserAsync(BrowserProxy* browser) const { server_->Send( new AutomationMsg_CloseBrowserRequestAsync(0, browser->handle())); } -bool UITest::CloseBrowser(BrowserProxy* browser, +bool UITestBase::CloseBrowser(BrowserProxy* browser, bool* application_closed) const { DCHECK(application_closed); if (!browser->is_valid() || !browser->handle()) @@ -830,7 +823,7 @@ bool UITest::CloseBrowser(BrowserProxy* browser, } // Static -FilePath UITest::GetTestFilePath(const std::wstring& test_directory, +FilePath UITestBase::GetTestFilePath(const std::wstring& test_directory, const std::wstring& test_case) { FilePath path; PathService::Get(chrome::DIR_TEST_DATA, &path); @@ -840,12 +833,12 @@ FilePath UITest::GetTestFilePath(const std::wstring& test_directory, } // Static -GURL UITest::GetTestUrl(const std::wstring& test_directory, +GURL UITestBase::GetTestUrl(const std::wstring& test_directory, const std::wstring &test_case) { return net::FilePathToFileURL(GetTestFilePath(test_directory, test_case)); } -void UITest::WaitForFinish(const std::string &name, +void UITestBase::WaitForFinish(const std::string &name, const std::string &id, const GURL &url, const std::string& test_complete_cookie, @@ -872,7 +865,7 @@ void UITest::WaitForFinish(const std::string &name, EXPECT_EQ(true, test_result); } -void UITest::PrintResult(const std::string& measurement, +void UITestBase::PrintResult(const std::string& measurement, const std::string& modifier, const std::string& trace, size_t value, @@ -882,7 +875,7 @@ void UITest::PrintResult(const std::string& measurement, "", "", units, important); } -void UITest::PrintResult(const std::string& measurement, +void UITestBase::PrintResult(const std::string& measurement, const std::string& modifier, const std::string& trace, const std::string& value, @@ -892,7 +885,7 @@ void UITest::PrintResult(const std::string& measurement, important); } -void UITest::PrintResultMeanAndError(const std::string& measurement, +void UITestBase::PrintResultMeanAndError(const std::string& measurement, const std::string& modifier, const std::string& trace, const std::string& mean_and_error, @@ -902,7 +895,7 @@ void UITest::PrintResultMeanAndError(const std::string& measurement, "{", "}", units, important); } -void UITest::PrintResultList(const std::string& measurement, +void UITestBase::PrintResultList(const std::string& measurement, const std::string& modifier, const std::string& trace, const std::string& values, @@ -912,7 +905,7 @@ void UITest::PrintResultList(const std::string& measurement, "[", "]", units, important); } -void UITest::PrintResultsImpl(const std::string& measurement, +void UITestBase::PrintResultsImpl(const std::string& measurement, const std::string& modifier, const std::string& trace, const std::string& values, @@ -929,7 +922,7 @@ void UITest::PrintResultsImpl(const std::string& measurement, units.c_str()); } -bool UITest::EvictFileFromSystemCacheWrapper(const FilePath& path) { +bool UITestBase::EvictFileFromSystemCacheWrapper(const FilePath& path) { for (int i = 0; i < 10; i++) { if (file_util::EvictFileFromSystemCache(path)) return true; @@ -939,7 +932,7 @@ bool UITest::EvictFileFromSystemCacheWrapper(const FilePath& path) { } // static -void UITest::RewritePreferencesFile(const FilePath& user_data_dir) { +void UITestBase::RewritePreferencesFile(const FilePath& user_data_dir) { const FilePath pref_template_path( user_data_dir.AppendASCII("Default").AppendASCII("PreferencesTemplate")); const FilePath pref_path( @@ -972,25 +965,25 @@ void UITest::RewritePreferencesFile(const FilePath& user_data_dir) { } // static -FilePath UITest::ComputeTypicalUserDataSource(ProfileType profile_type) { +FilePath UITestBase::ComputeTypicalUserDataSource(ProfileType profile_type) { FilePath source_history_file; EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_history_file)); source_history_file = source_history_file.AppendASCII("profiles"); switch (profile_type) { - case UITest::DEFAULT_THEME: + case UITestBase::DEFAULT_THEME: source_history_file = source_history_file.AppendASCII("typical_history"); break; - case UITest::COMPLEX_THEME: + case UITestBase::COMPLEX_THEME: source_history_file = source_history_file.AppendASCII("complex_theme"); break; - case UITest::NATIVE_THEME: + case UITestBase::NATIVE_THEME: source_history_file = source_history_file.AppendASCII("gtk_theme"); break; - case UITest::CUSTOM_FRAME: + case UITestBase::CUSTOM_FRAME: source_history_file = source_history_file.AppendASCII("custom_frame"); break; - case UITest::CUSTOM_FRAME_NATIVE_THEME: + case UITestBase::CUSTOM_FRAME_NATIVE_THEME: source_history_file = source_history_file.AppendASCII("custom_frame_gtk_theme"); break; @@ -1000,7 +993,7 @@ FilePath UITest::ComputeTypicalUserDataSource(ProfileType profile_type) { return source_history_file; } -void UITest::WaitForGeneratedFileAndCheck(const FilePath& generated_file, +void UITestBase::WaitForGeneratedFileAndCheck(const FilePath& generated_file, const FilePath& original_file, bool compare_files, bool need_equal, @@ -1043,7 +1036,7 @@ void UITest::WaitForGeneratedFileAndCheck(const FilePath& generated_file, EXPECT_TRUE(file_util::DieFileDie(generated_file, false)); } -bool UITest::LaunchBrowserHelper(const CommandLine& arguments, +bool UITestBase::LaunchBrowserHelper(const CommandLine& arguments, bool use_existing_browser, bool wait, base::ProcessHandle* process) { @@ -1193,7 +1186,7 @@ bool UITest::LaunchBrowserHelper(const CommandLine& arguments, return true; } -void UITest::UpdateHistoryDates() { +void UITestBase::UpdateHistoryDates() { // Migrate the times in the segment_usage table to yesterday so we get // actual thumbnails on the NTP. sql::Connection db; @@ -1216,7 +1209,7 @@ void UITest::UpdateHistoryDates() { file_util::EvictFileFromSystemCache(history); } -void UITest::PrintIOPerfInfo(const char* test_name) { +void UITestBase::PrintIOPerfInfo(const char* test_name) { ChromeProcessList chrome_processes(GetRunningChromeProcesses(process_id_)); size_t read_op_b = 0; @@ -1322,7 +1315,7 @@ void UITest::PrintIOPerfInfo(const char* test_name) { PrintResult("total_byte_r", "", "IO_r" + t_name, total_byte_r, "kb", true); } -void UITest::PrintMemoryUsageInfo(const char* test_name) { +void UITestBase::PrintMemoryUsageInfo(const char* test_name) { ChromeProcessList chrome_processes(GetRunningChromeProcesses(process_id_)); size_t browser_virtual_size = 0; @@ -1454,14 +1447,14 @@ void UITest::PrintMemoryUsageInfo(const char* test_name) { false /* not important */); } -void UITest::PrintSystemCommitCharge(const char* test_name, +void UITestBase::PrintSystemCommitCharge(const char* test_name, size_t charge, bool important) { std::string trace_name(test_name); PrintResult("commit_charge", "", "cc" + trace_name, charge, "kb", important); } -void UITest::UseReferenceBuild() { +void UITestBase::UseReferenceBuild() { FilePath dir; PathService::Get(chrome::DIR_TEST_TOOLS, &dir); dir = dir.AppendASCII("reference_build"); @@ -1475,3 +1468,25 @@ void UITest::UseReferenceBuild() { browser_directory_ = dir; } +// UITest methods + +void UITest::SetUp() { + // Pass the test case name to chrome.exe on the command line to help with + // parsing Purify output. + const testing::TestInfo* const test_info = + testing::UnitTest::GetInstance()->current_test_info(); + if (test_info) { + std::string test_name = test_info->test_case_name(); + test_name += "."; + test_name += test_info->name(); + set_ui_test_name(ASCIIToWide(test_name)); + } + UITestBase::SetUp(); + PlatformTest::SetUp(); +} + +void UITest::TearDown() { + UITestBase::TearDown(); + PlatformTest::TearDown(); +} + diff --git a/chrome/test/ui/ui_test.h b/chrome/test/ui/ui_test.h index 367d8b9a..48b1b90 100644 --- a/chrome/test/ui/ui_test.h +++ b/chrome/test/ui/ui_test.h @@ -40,14 +40,21 @@ class FilePath; class GURL; class TabProxy; -class UITest : public PlatformTest { +// Base class for UI Tests. This implements the core of the functions. +// This base class decouples all automation functionality from testing +// infrastructure, for use without gtest. +// If using gtest, you probably want to inherit from UITest (declared below) +// rather than UITestBase. +class UITestBase { protected: // String to display when a test fails because the crash service isn't // running. static const wchar_t kFailedNoCrashService[]; // Constructor - UITest(); + UITestBase(); + + virtual ~UITestBase(); // Starts the browser using the arguments in launch_arguments_, and // sets up member variables. @@ -404,6 +411,10 @@ class UITest : public PlatformTest { std::wstring ui_test_name() const { return ui_test_name_; } + void set_ui_test_name(const std::wstring& name) { + ui_test_name_ = name; + } + // Count the number of active browser processes launched by this test. // The count includes browser sub-processes. int GetBrowserProcessCount(); @@ -591,6 +602,12 @@ class UITest : public PlatformTest { std::wstring ui_test_name_; }; +class UITest : public UITestBase, public PlatformTest { + protected: + virtual void SetUp(); + virtual void TearDown(); +}; + // These exist only to support the gTest assertion macros, and // shouldn't be used in normal program code. #ifdef UNIT_TEST |