Good day-

Going along with the user.js I sent to the list a few days ago, this
Python module makes driving Selenium from Python a cinch.

All you need to do is instantiate SeleniumGateway with a socket-address
tuple.  Then call the execute() method with the parts of your Selenese
command as arguments. Example:

    s = SeleniumGateway(('127.0.0.1', 8080))
    s.execute('type', 'id=InputField', 'The Text')

Now point your browser at your Selenium runner, which should be
requesting commands from http://localhost:8080/driver .

The return string from each Selenium command is returned by execute().

The SeleniumGateway still works if you modify your Selenese runner HTML
to submit queries with POST instead of GET, as we do. We find this works
much better when we expect to receive longer result strings or more
complicated ones.

I'd very much appreciate feedback on this approach and the user.js file
I sent. We hope to be able to work with others using this or similar
code.

-- 
paul
# SeleniumGateway
#
# Written by paul cannon at Novell, Inc. for the Selenium system.

from cgi import parse_qs
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
from StringIO import StringIO

class SeleniumGatewayError(Exception): pass

class SeleniumRequestHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        self.start_reply_then_postpone(parse_qs(self.rfile.read(
            int(self.headers.getheader('content-length'))
        )))

    def do_GET(self):
        qmark = self.path.find('?')
        if qmark < 0:
            querystr = ''
        else:
            querystr = self.path[qmark+1:]
        self.start_reply_then_postpone(parse_qs(querystr))

    def start_reply_then_postpone(self, queryvars):
        result = queryvars.get('commandResult', [None])[0]
        self.send_response(200)
        self.send_header("Content-type", "text/plain")
        self.end_headers()
        self.server.export_client_and_result(
            self.save_wfile_for_later(),
            result
        )

    def save_wfile_for_later(self):
        """Deviousness. Move the wfile stream and replace it with a fake
        one, so the underlying SocketStream foo can close it and think it's
        safely done. We won't reply to this request until a new command is
        available.
        """

        waiting_client = self.wfile
        self.wfile = StringIO()
        return waiting_client

    def log_message(self, format, *args):
        # throw away webserverish logs for now
        pass

class SeleniumGateway:
    def __init__(self, server_addr):
        self.server_addr = server_addr
        self.server = HTTPServer(server_addr, SeleniumRequestHandler)
        self.server.export_client_and_result = self.acquire_client_and_result
        if self.get_result() is not None:  # should give None for first call
            raise SeleniumGatewayError(
                "Browser is not synchronized with SeleniumGateway"
            )

    @staticmethod
    def buildselenese(selcmd, seltarget='', selvalue=''):
        return '|%s|%s|%s|' % (selcmd, seltarget, selvalue)

    def send_string(self, command):
        self.waiting_client.write(command)
        self.waiting_client.close()
        del self.waiting_client

    def get_result(self):
        self.server.handle_request()
        result = self.selenium_result
        del self.selenium_result
        return result

    def execute(self, selcmd, seltarget='', selvalue=''):
        self.send_string(self.buildselenese(selcmd, seltarget, selvalue))
        return self.get_result()

    def acquire_client_and_result(self, client, result):
        self.waiting_client = client
        self.selenium_result = result
_______________________________________________
Selenium-devel mailing list
Selenium-devel@lists.public.thoughtworks.org
http://lists.public.thoughtworks.org/mailman/listinfo/selenium-devel

Reply via email to