Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,19 @@ which follows the example of Robot assertions and makes it obvious that the meth
Page object assertion methods shouldn't change the state of the page (eg. clicking links, navigating back etc.) and minimal computation, looping etc. State change and computation should be done in page object action/helper methods. In your test,
you should get the page to the state where you want it to be using other page object methods, and call the assert method.

## Sauce Labs Cloud Testing Service Integration

robotframework-pageobjects integrates seamlessly with
[Sauce Labs](http://saucelabs.com/), a cloud service allowing you to run Selenium-based
jobs on a [multitude of browsers and platforms](https://docs.saucelabs.com/reference/platforms-configurator/#/).
Simply set at least the `sauce_apikey`, `sauce_username`, `sauce_platform` and the `browser`
built-in IFT options. See the Built-in options section [above](#built-in-options-for-page) for options
related to running tests in Sauce.

Your page objects will automatically tag your Robot Sauce jobs with their
associated test names and
test status.

## Logging Reporting & Debugging

### Robot
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ decorator
mock==1.0.1
requests==2.1.0
robotframework-selenium2library==1.6.0
python-saucerest
uritemplate==0.6
68 changes: 68 additions & 0 deletions robotpageobjects/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from . import exceptions
from .context import Context
from .optionhandler import OptionHandler
import saucelabs.saucerest as saucerest


class _Keywords(object):
Expand Down Expand Up @@ -523,6 +524,69 @@ class _BaseActions(_S2LWrapper):
"""

_abstracted_logger = abstractedlogger.Logger()
ROBOT_LISTENER_API_VERSION = 2

# For keeping track if we've tagged a sauce
# job.
_session_to_test_hash = {}

@property
def _sauce_job_registered(self):
return self.session_id in self._session_to_test_hash

def _register_sauce_job(self):
self._session_to_test_hash[self.session_id] = self._current_test

def _start_test(self, name, attrs):
self._current_test = name

def _end_test(self, name, attrs):
self.log("Tag sauce job, %s with %s" %(self.session_id, attrs["status"]))
passed = attrs["status"] == "PASS"
self._saucerest.update_job(self.session_id, dict(passed=passed))

def _end_keyword(self, name, attrs):
""" Called after every keyword is called in Robot test.
We need to get the session ID here, and initialize sauce tagging
here because the browser must
first be open to get a session ID, and thus be able to tag a
sauce job. We can only be assured of this once we've called
a keyword that's ultimately called SE2Lib's Open Browser
keyword.
"""
session_id = None

# Wait until we have a session ID
try:
session_id = self.session_id

except AttributeError:
return

# If we haven't tagged this job then,
# initialize a sauce rest object and tag.
if not self._sauce_job_registered:
self.log("Tag sauce job %s with %s" %(session_id, self._current_test))

# Have we initialized a saucerest object already?
try:
self._saucerest
except AttributeError:
self._saucerest = saucerest.SauceRest(
username=self.sauce_username,
password=self.sauce_apikey
)

# We should have a saucerest object by now
# so go ahead and tag the job with the name of
# the Robot test.
self._saucerest.update_job(
session_id,
dict(name=self._current_test)
)

# Sets the flag whether we've already tagged this job
self._register_sauce_job()

def __init__(self, *args, **kwargs):
"""
Expand All @@ -532,6 +596,10 @@ def __init__(self, *args, **kwargs):
#_SelectorsManager.__init__(self, *args, **kwargs)
super(_BaseActions, self).__init__(*args, **kwargs)

# Make this library a listener so we can
# centralize robot listener hooks, esp. for
# sauce.
self.ROBOT_LIBRARY_LISTENER = self
self._option_handler = OptionHandler()
self._is_robot = Context.in_robot()
self.selenium_speed = self._option_handler.get("selenium_speed") or 0
Expand Down
1 change: 1 addition & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ scenarios directory. In general each functional test is executed both in the Rob
unittest context. Functional tests are found in functional.py. They run actual browsers. Unittests are found in unit
.py and test simple inputs and outputs of critical page object methods and helpers.

- Install nose with `$ pip install nose`, then run tests: $ nosetests -vs tests/test_unit.py tests/test_functional.py`.
- The `scenarios` directory contains the unittests and robot tests which the page object framework tests call in a
subprocess.
- The `site` directory contains the sample site under test
Expand Down