Bug 756233: Removing Selenium proxy from marionette r=jgriffin
authorDavid Burns <dburns@mozilla.com>
Tue, 22 May 2012 07:09:46 -0700
changeset 96825 b6d88d5947835a10f9819154824ad2a45137f6e1
parent 96824 d50e4a17308b13c66ad800483fe9b69f304f9a5d
child 96826 c20d415ef1b50fc6cd9751d5dbe79434307f50b4
push id1439
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 20:19:22 +0000
treeherdermozilla-aurora@ea74834dccd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgriffin
bugs756233
milestone15.0a1
Bug 756233: Removing Selenium proxy from marionette r=jgriffin
testing/marionette/client/README.md
testing/marionette/client/marionette/selenium_proxy.py
testing/marionette/client/marionette/test_selenium.py
--- a/testing/marionette/client/README.md
+++ b/testing/marionette/client/README.md
@@ -16,36 +16,29 @@ although not all commands are presently 
 will likely be added.
 
 ## Package Files
 
 - client.py:  This is the Marionette socket client; it speaks the same
   socket protocol as the Gecko remote debugger.
 - marionette.py:  The Marionette client.  This uses client.py to communicate
   with a server that speaks the Gecko remote debugger protocol.
-- selenium_proxy.py:  Acts as a remote driver for Selenium test runners.
-  This code translates the Selenium 
-  [JSON Wire Protocol](http://code.google.com/p/selenium/wiki/JsonWireProtocol)
-  to the [Marionette JSON Protocol](https://wiki.mozilla.org/Auto-tools/Projects/Marionette/JSON_Protocol).
   This allows Selenium tests to utilize Marionette.
 - testserver.py:  A socket server which mimics the remote debugger in
   Gecko, and can be used to test pieces of the Marionette client.
 - test_protocol.py:  Tests the Marionette JSON Protocol by using testserver.py.
-- test_selenium.py:  Tests the Selenium proxy by using testserver.py.
 
 ## Installation
 
 You'll need the ManifestDestiny and MozHttpd packages from Mozbase:
 
     git clone git://github.com/mozilla/mozbase.git
     cd mozbase
     python setup_development.py
 
-Other than that, there are no special requirements, unless you're using the Selenium proxy, in which
-case you'll need to install the Selenium Python bindings using:
+Other than that, there are no special requirements.
 
-    pip install selenium
 
 ## Writing and Running Tests Using Marionette
 
 See [Writing Marionette tests](https://developer.mozilla.org/en/Marionette/Tests),
 and [Running Marionette tests](https://developer.mozilla.org/en/Marionette/Running_Tests).
 
deleted file mode 100644
--- a/testing/marionette/client/marionette/selenium_proxy.py
+++ /dev/null
@@ -1,265 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import BaseHTTPServer
-import json
-import re
-import traceback
-
-from errors import *
-from marionette import Marionette, HTMLElement
-
-class SeleniumRequestServer(BaseHTTPServer.HTTPServer):
-
-    def __init__(self, marionette, *args, **kwargs):
-        self.marionette = marionette
-        BaseHTTPServer.HTTPServer.__init__(self, *args, **kwargs)
-
-    def __del__(self):
-        if self.marionette.server:
-            self.marionette.delete_session()
-
-class SeleniumRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
-
-    pathRe = re.compile(r'/session/(.*?)/((element/(.*?)/)?(.*))')
-
-    def server_error(self, error):
-        self.send_response(500)
-        self.send_header("Content-type", "application/json")
-        self.end_headers()
-        self.wfile.write(json.dumps({'status': 500, 'value': {'message': error}}))
-
-    def file_not_found(self):
-        self.send_response(404)
-        self.send_header("Content-type", "application/json")
-        self.end_headers()
-        self.wfile.write(json.dumps({'status': 404, 'value': {'message': '%s not found' % self.path}}))
-
-    def send_JSON(self, data=None, session=None, value=None):
-        self.send_response(200)
-        self.send_header("Content-type", "application/json")
-        self.end_headers()
-
-        if data is None:
-            data = {}
-        if not 'status' in data:
-            data['status'] = 0
-        if session is not None:
-            data['sessionId'] = session
-        if value is None:
-            data['value'] = {}
-        else:
-            data['value'] = value
-
-        self.wfile.write(json.dumps(data))
-
-    def process_request(self):
-        session = body = None
-        path = self.path
-        element = None
-        m = self.pathRe.match(self.path)
-        if m:
-            session = m.group(1)
-            element = m.group(4)
-            path = '/%s' % m.group(5)
-        content_len = self.headers.getheader('content-length')
-        if content_len:
-            body = json.loads(self.rfile.read(int(content_len)))
-        return path, body, session, element
-
-    def do_DELETE(self):
-        try:
-
-            path, body, session, element = self.process_request()
-
-            if path == '/session':
-                assert(session)
-                assert(self.server.marionette.delete_session())
-                self.send_JSON(session=session)
-            elif path == '/window':
-                assert(session)
-                assert(self.server.marionette.close_window())
-                self.send_JSON(session=session)
-            else:
-                self.file_not_found()
-
-        except MarionetteException, e:
-            self.send_JSON(data={'status': e.status}, value={'message': e.message})
-        except:
-            self.server_error(traceback.format_exc())
-
-    def do_GET(self):
-        try:
-
-            path, body, session, element = self.process_request()
-
-            if path.startswith('/attribute/'):
-                assert(session)
-                name = path[len('/attribute/'):]
-                marionette_element = HTMLElement(self.server.marionette, element)
-                self.send_JSON(session=session,
-                               value=marionette_element.get_attribute(name))
-            elif path == '/displayed':
-                assert(session)
-                marionette_element = HTMLElement(self.server.marionette, element)
-                self.send_JSON(session=session,
-                               value=marionette_element.displayed())
-            elif path == '/enabled':
-                assert(session)
-                marionette_element = HTMLElement(self.server.marionette, element)
-                self.send_JSON(session=session,
-                               value=marionette_element.enabled())
-            elif path.startswith('/equals/'):
-                assert(session)
-                other = path[len('/equals'):]
-                marionette_element = HTMLElement(self.server.marionette, element)
-                other_element = HTMLElement(self.server.marionette, other)
-                self.send_JSON(session=session,
-                               value=marionette_element.equals(other))
-            elif path == '/selected':
-                assert(session)
-                marionette_element = HTMLElement(self.server.marionette, element)
-                self.send_JSON(session=session,
-                               value=marionette_element.selected())
-            elif path == '/status':
-                self.send_JSON(data=self.server.marionette.status())
-            elif path == '/text':
-                assert(session)
-                marionette_element = HTMLElement(self.server.marionette, element)
-                self.send_JSON(session=session,
-                               value=marionette_element.text())
-            elif path == '/url':
-                assert(session)
-                self.send_JSON(value=self.server.marionette.get_url(),
-                               session=session)
-            elif path == '/value':
-                assert(session)
-                marionette_element = HTMLElement(self.server.marionette, element)
-                send.send_JSON(session=session,
-                               value=marionette_element.value())
-            elif path == '/window_handle':
-                assert(session)
-                self.send_JSON(session=session,
-                               value=self.server.marionette.get_window())
-            elif path == '/window_handles':
-                assert(session)
-                self.send_JSON(session=session,
-                               value=self.server.marionette.get_windows())
-            else:
-                self.file_not_found()
-
-        except MarionetteException, e:
-            self.send_JSON(data={'status': e.status}, value={'message': e.message})
-        except:
-            self.server_error(traceback.format_exc())
-
-    def do_POST(self):
-        try:
-
-            path, body, session, element = self.process_request()
-
-            if path == '/back':
-                assert(session)
-                assert(self.server.marionette.go_back())
-                self.send_JSON(session=session)
-            elif path == '/clear':
-                assert(session)
-                marionette_element = HTMLElement(self.server.marionette, element)
-                marionette_element.clear()
-                self.send_JSON(session=session)
-            elif path == '/click':
-                assert(session)
-                marionette_element = HTMLElement(self.server.marionette, element)
-                marionette_element.click()
-                self.send_JSON(session=session)
-            elif path == '/element':
-                # find element variants
-                assert(session)
-                self.send_JSON(session=session,
-                               value={'ELEMENT': str(self.server.marionette.find_element(body['using'], body['value'], id=element))})
-            elif path == '/elements':
-                # find elements variants
-                assert(session)
-                self.send_JSON(session=session,
-                               value=[{'ELEMENT': str(x)} for x in self.server.marionette.find_elements(body['using'], body['value'])])
-            elif path == '/execute':
-                assert(session)
-                if body['args']:
-                    result = self.server.marionette.execute_script(body['script'], script_args=body['args'])
-                else:
-                    result = self.server.marionette.execute_script(body['script'])
-                self.send_JSON(session=session, value=result)
-            elif path == '/execute_async':
-                assert(session)
-                if body['args']:
-                    result = self.server.marionette.execute_async_script(body['script'], script_args=body['args'])
-                else:
-                    result = self.server.marionette.execute_async_script(body['script'])
-                self.send_JSON(session=session, value=result)
-            elif path == '/forward':
-                assert(session)
-                assert(self.server.marionette.go_forward())
-                self.send_JSON(session=session)
-            elif path == '/frame':
-                assert(session)
-                frame = body['id']
-                if isinstance(frame, dict) and 'ELEMENT' in frame:
-                    frame = HTMLElement(self.server.marionette, frame['ELEMENT'])
-                assert(self.server.marionette.switch_to_frame(frame))
-                self.send_JSON(session=session)
-            elif path == '/refresh':
-                assert(session)
-                assert(self.server.marionette.refresh())
-                self.send_JSON(session=session)
-            elif path == '/session':
-                session = self.server.marionette.start_session()
-                # 'value' is the browser capabilities, which we're ignoring for now
-                self.send_JSON(session=session, value={})
-            elif path == '/timeouts/async_script':
-                assert(session)
-                assert(self.server.marionette.set_script_timeout(body['ms']))
-                self.send_JSON(session=session)
-            elif path == '/timeouts/implicit_wait':
-                assert(session)
-                assert(self.server.marionette.set_search_timeout(body['ms']))
-                self.send_JSON(session=session)
-            elif path == '/url':
-                assert(session)
-                assert(self.server.marionette.navigate(body['url']))
-                self.send_JSON(session=session)
-            elif path == '/value':
-                assert(session)
-                keys = ''.join(body['value'])
-                marionette_element = HTMLElement(self.server.marionette, element)
-                assert(marionette_element.send_keys(keys))
-                self.send_JSON(session=session)
-            elif path == '/window':
-                assert(session)
-                assert(self.server.marionette.switch_to_window(body['name']))
-                self.send_JSON(session=session)
-            else:
-                self.file_not_found()
-
-        except MarionetteException, e:
-            self.send_JSON(data={'status': e.status}, value={'message': e.message})
-        except:
-            self.server_error(traceback.format_exc())
-
-class SeleniumProxy(object):
-
-    def __init__(self, remote_host, remote_port, proxy_port=4444):
-        self.remote_host = remote_host
-        self.remote_port = remote_port
-        self.proxy_port = proxy_port
-
-    def start(self):
-        marionette = Marionette(self.remote_host, self.remote_port)
-        httpd = SeleniumRequestServer(marionette,
-                                      ('127.0.0.1', self.proxy_port),
-                                      SeleniumRequestHandler)
-        httpd.serve_forever()
-
-if __name__ == "__main__":
-    proxy = SeleniumProxy('localhost', 2626)
-    proxy.start()
deleted file mode 100644
--- a/testing/marionette/client/marionette/test_selenium.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-import threading
-
-try:
-    from selenium import webdriver
-    from selenium.common.exceptions import *
-    from selenium.webdriver.remote.webelement import WebElement
-except:
-    print 'requires selenium Python bindings; pip install selenium'
-    raise
-from selenium_proxy import SeleniumProxy
-from testserver import TestServer
-
-def test_find_element(driver, fn):
-    """ Test a find_element_by_FOO method of both the webdriver
-        and the WebElement class.  The former will return a WebElement which
-        should have a method of the same name, which should also return
-        a WebElement.
-    """
-    element = getattr(driver, fn)('foo')
-    assert(isinstance(element, WebElement))
-    assert(element.id == TestServer.TEST_FIND_ELEMENT)
-    child = getattr(element, fn)('foo')
-    assert(isinstance(child, WebElement))
-    assert(child.id == TestServer.TEST_FIND_ELEMENT)
-
-def test_find_elements(driver, fn):
-    """ Test a find_elements_by_FOO method of both the webdriver
-        and the WebElement class.  The former will return a list of 
-        WebElements, each of which should have a method of the same name,
-        and which in should turn should also return a list of WebElements.
-    """
-    elements = getattr(driver, fn)('foo')
-    # elements should be a list
-    assert(isinstance(elements, list))
-    # elements should match the TEST_FIND_ELEMENTS list
-    assert(map(lambda x: x.id, elements) == TestServer.TEST_FIND_ELEMENTS)
-    # Each member of elements should be a WebElement that has the same
-    # method, which should in turn return a list of WebElements when called.
-    for element in elements:
-        assert(isinstance(element, WebElement))
-        children = getattr(element, fn)('foo')
-        assert(isinstance(children, list))
-        assert(map(lambda x: x.id, children) == TestServer.TEST_FIND_ELEMENTS)
-        assert(len(filter(lambda x: not isinstance(x, WebElement), children)) == 0)
-
-if __name__ == '__main__':
-    # start the test server on port 2626
-    server = TestServer(2626)
-    thread = threading.Thread(target=server.run)
-    thread.daemon = True
-    thread.start()
-
-    # Start the selenium proxy on port 4444, connecting to the test server
-    # on port 2626.
-    proxy = SeleniumProxy('127.0.0.1', 2626, proxy_port=4444)
-    proxy_thread = threading.Thread(target=proxy.start)
-    proxy_thread.daemon = True
-    proxy_thread.start()
-
-    # invoke selenium commands as tests
-    driver = webdriver.Remote(command_executor='http://127.0.0.1:4444',
-                              desired_capabilities=webdriver.DesiredCapabilities.FIREFOX)
-    assert(driver)
-
-    # test navigation methods
-    driver.get(TestServer.TEST_URL)
-    assert(driver.current_url == TestServer.TEST_URL)
-    driver.back()
-    driver.forward()
-    driver.refresh()
-
-    # test script methods
-    driver.set_script_timeout(10) # in selenium the number is in seconds
-    driver.implicitly_wait(10)    # ditto
-
-    assert(TestServer.TEST_EXECUTE_RETURN_VALUE == driver.execute_script(TestServer.TEST_EXECUTE_SCRIPT))
-    assert(TestServer.TEST_EXECUTE_RETURN_VALUE == driver.execute_script(TestServer.TEST_EXECUTE_SCRIPT,
-                                                                         TestServer.TEST_EXECUTE_SCRIPT_ARGS))
-    assert(TestServer.TEST_EXECUTE_RETURN_VALUE == driver.execute_async_script(TestServer.TEST_EXECUTE_SCRIPT))
-    assert(TestServer.TEST_EXECUTE_RETURN_VALUE == driver.execute_async_script(TestServer.TEST_EXECUTE_SCRIPT,
-                                                                               TestServer.TEST_EXECUTE_SCRIPT_ARGS))
-
-    # test all the find_element_by_FOO methods
-    test_find_element(driver, 'find_element_by_name')
-    test_find_element(driver, 'find_element_by_id')
-    test_find_element(driver, 'find_element_by_xpath')
-    test_find_element(driver, 'find_element_by_link_text')
-    test_find_element(driver, 'find_element_by_partial_link_text')
-    test_find_element(driver, 'find_element_by_tag_name')
-    test_find_element(driver, 'find_element_by_class_name')
-    test_find_element(driver, 'find_element_by_css_selector')
-
-    # test all the find_elements_by_FOO methods
-    test_find_elements(driver, 'find_elements_by_name')
-    test_find_elements(driver, 'find_elements_by_id')
-    test_find_elements(driver, 'find_elements_by_xpath')
-    test_find_elements(driver, 'find_elements_by_link_text')
-    test_find_elements(driver, 'find_elements_by_partial_link_text')
-    test_find_elements(driver, 'find_elements_by_tag_name')
-    test_find_elements(driver, 'find_elements_by_class_name')
-    test_find_elements(driver, 'find_elements_by_css_selector')
-
-    # test WebElement methods
-    element = driver.find_element_by_name('foo')
-    element.click()
-    assert(element.text == TestServer.TEST_GET_TEXT)
-    element.send_keys('Mozilla Firefox')
-    element.clear()
-    assert(element.is_selected())
-    assert(element.is_enabled())
-    assert(element.is_displayed())
-    assert(element.get_attribute('id') == TestServer.TEST_GET_VALUE)
-
-    # make the server return error responses so we can test them
-    server.responses = server.error_responses
-
-    # test exception handling
-    try:
-        driver.execute_async_script(TestServer.TEST_EXECUTE_SCRIPT)
-        assert(False)
-    except TimeoutException:
-        # the Selenium Python driver maps SCRIPT_TIMEOUT to TIMEOUT
-        pass
-
-    try:
-        driver.execute_script(TestServer.TEST_EXECUTE_SCRIPT)
-        assert(False)
-    except WebDriverException:
-        # the Selenium Python driver doesn't specifically support JAVASCRIPT_ERROR
-        pass
-
-    try:
-        driver.find_element_by_name('foo')
-        assert(False)
-    except NoSuchElementException:
-        pass
-
-    try:
-        driver.find_elements_by_name('foo')
-        assert(False)
-    except WebDriverException:
-        # the Selenium Python driver doesn't specifically support XPATH_LOOKUP_ERROR
-        pass
-
-    try:
-        driver.close()
-        assert(False)
-    except NoSuchWindowException:
-        pass
-
-    try:
-        element.click()
-        assert(False)
-    except StaleElementReferenceException:
-        pass
-
-    try:
-        element.send_keys('Mozilla Firefox')
-        assert(False)
-    except ElementNotVisibleException:
-        pass
-
-    try:
-        driver.switch_to_frame('aframe')
-        assert(False)
-    except NoSuchFrameException:
-        pass
-
-    # restore normal test responses
-    server.responses = server.test_responses
-
-    # test window methods
-    assert(driver.current_window_handle == TestServer.TEST_CURRENT_WINDOW)
-    assert(driver.window_handles == TestServer.TEST_WINDOW_LIST)
-    driver.switch_to_window(TestServer.TEST_CURRENT_WINDOW)
-
-    # test frame methods
-    driver.switch_to_frame('aframe') # by name or id
-    driver.switch_to_frame(1)        # by index
-    driver.switch_to_frame(element)  # by element reference
-    driver.switch_to_frame(None)     # null; switch to default frame
-
-    driver.close() # this is close_window
-
-    print 'Tests complete!'
-