Commit d61b80d2 authored by Douglas's avatar Douglas

jstestnode: added support for running tests with Selenium Remote and Appium

It uses Appium, which provides a Selenium WebDrivercompatible API to remotely control an iOS (or Android) simulator.This way we can run tests in both mobile OSes without big changesto the current test code and infrastructure.

This allows user to customize in the test suite module on which systemthey want to run the tests (Firefox or iOS) through the slapos parameters.In iOS, for example, it's possible to change the iOS version and it's requiredthat the user give the SauceLabs credentials in form of user:apikey usingthe `appium_server_auth` parameter.

An example of parameters to use in a this suite:

```
{"mariadb": {  "relaxed-writes": true,  "mariadb-relaxed-writes": true,  "test-database-amount": 30},  "target": "ios",  "target-version": "9.3",  "appium-server-auth": "username:api_key  "test-suite" : "jio" ,  "test-url": "jio-repository.git/test/tests.html" }
```
parent cbcf4793
......@@ -58,6 +58,7 @@ class Recipe(GenericBaseRecipe):
"\npath_list = %s" % ",".join(software_path_list)
CONFIG['computer_id'] = self.buildout['slap-connection']['computer-id']
CONFIG['server_url'] = self.buildout['slap-connection']['server-url']
CONFIG['frontend_url'] = self.buildout['testnode-frontend']['connection-secure_access']
configuration_file = self.createFile(
self.options['configuration-file'],
self.substituteTemplate(
......
......@@ -18,6 +18,7 @@ httpd_port = %(httpd_port)s
httpd_software_access_port = %(httpd_software_access_port)s
computer_id = %(computer_id)s
server_url = %(server_url)s
frontend_url = %(frontend_url)s
# Binaries
git_binary = %(git_binary)s
......
......@@ -76,8 +76,7 @@ SSLProxyEngine On
Listen [%(ip)s]:%(software_access_port)s
<VirtualHost *:%(software_access_port)s>
SSLEngine on
RewriteRule (.*) http://[%(ip)s]:%(software_access_port)s/VirtualHostBase/https/[%(ip)s]:%(software_access_port)s/VirtualHostRoot/$1 [L,P]
DocumentRoot "%(testnode_software_directory)s"
DocumentRoot "%(testnode_srv_directory)s"
<Directory />
Options FollowSymLinks
IndexOptions FancyIndexing
......
......@@ -2,7 +2,6 @@
parts =
nginx-service
runTestSuite-instance
eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true
......@@ -36,6 +35,7 @@ framebuffer = $${:srv}/framebuffer
recipe = slapos.recipe.template
url = ${template-runTestSuite:output}
output = $${directory:bin}/runTestSuite
buildout-directory = $${buildout:directory}
mode = 0700
[firefox-instance]
......@@ -76,7 +76,7 @@ output = $${directory:etc}/nginx.cfg
mode = 0600
access_log = $${directory:log}/nginx-access.log
error_log = $${directory:log}/nginx-error.log
ip = $${instance-parameter:ipv6-random}
ip = $${instance-parameters:ipv6-random}
port = 9443
ssl_key = $${directory:ssl}/nginx.key
ssl_csr = $${directory:ssl}/nginx.csr
......@@ -85,7 +85,7 @@ ssl_crt = $${directory:ssl}/nginx.crt
#################################
# SlapOS service
#################################
[instance-parameter]
[instance-parameters]
recipe = slapos.cookbook:slapconfiguration
computer = $${slap_connection:computer_id}
partition = $${slap_connection:partition_id}
......
......@@ -31,9 +31,33 @@ def main():
parser.add_argument('--node_quantity', help='ignored', type=int)
parser.add_argument('--master_url',
help='The Url of Master controling many suites')
parser.add_argument('--frontend_url',
help='The url of frontend of the test suite')
parser.add_argument('--target',
help='Target OS to run tests on',
type=str)
parser.add_argument('--target_version',
help='Target OS version to use',
type=str,)
parser.add_argument('--appium_server_auth',
help='Combination of user and token to access SauceLabs service. (i.e. user:token)',
type=str)
args = parser.parse_args()
import json
parsed_parameters = json.loads('$${instance-parameters:configuration._}')
if not getattr(args, 'target', None):
args.target = parsed_parameters['target']
if not getattr(args, 'test_suite', None):
args.test_suite = parsed_parameters['test-suite']
if not getattr(args, 'target_version', None):
args.target_version = parsed_parameters['target-version']
if not getattr(args, 'appium_server_auth', None):
args.appium_server_auth = parsed_parameters['appium-server-auth']
try:
test_suite_title = args.test_suite_title or args.test_suite
test_suite = args.test_suite
......@@ -51,8 +75,27 @@ def main():
##########################
# Run all tests
##########################
if args.target == 'firefox':
firefox_binary = webdriver.firefox.firefox_binary.FirefoxBinary(firefox_path=FIREFOX_EXECUTABLE)
browser = webdriver.Firefox(firefox_binary=firefox_binary)
elif args.target == 'ios':
  • @Camata , no hard-coding here.

    Remember that target can be in theory any OS, not just iOS. Remember that by default due to legacy it's 'firefox' which despite bad name we must keep for backwards compatibility.

    Also please add new arguments to script like (keep in mind proper and already use notion for argument names). Also make sure that we can specify and pass them from 'Test Suite' parameters all the way the chain up to runTestSuite. This way we can fully test different combinations of OS/browser.

    • device_name

    • browser_name

Please register or sign in to reply
capabilities = {
'platformName': 'iOS',
'platformVersion': args.target_version,
'deviceName': 'iPhone Simulator',
'browserName': 'Safari'
}
if not args.appium_server_auth:
raise RuntimeError('--appium_server_auth is required.')
appium_url = "http://%s@ondemand.saucelabs.com/wd/hub" % (args.appium_server_auth)
browser = webdriver.Remote(appium_url, capabilities)
else:
raise RuntimeError('Unknown target')
full_path = '$${runTestSuite-instance:buildout-directory}/software_release/parts/%s' % parsed_parameters['test-url']
full_path = full_path.split('srv')[2]
url = "%s%s" % (args.frontend_url, full_path)
agent = browser.execute_script("return navigator.userAgent")
print agent
......@@ -67,7 +110,6 @@ def main():
body = etree.fromstring(browser.page_source.encode('UTF-8'), html_parser)
browser.title.encode('UTF-8')
browser.quit()
  • @Camata , why is that line removed? Looks inconsistent to me, please double check in order to not introduce regression.

  • There is a block below in the same file that will quit the browser even if an exception happened:

    ....
      finally:
        browser.quit()
    Edited by Douglas
Please register or sign in to reply
print ' '.join(body.xpath('//*[@id="qunit-testresult"]//text()'))
......@@ -99,7 +141,7 @@ def main():
node_title = args.test_node_title,
test_title = test_suite_title,
project_title = args.project_title)
if test_result is None:
if test_result is None or not hasattr(args, 'master_url'):
return
# report test results
while 1:
......
......@@ -25,7 +25,7 @@ parts =
[instance]
recipe = slapos.recipe.template
md5sum = 25a9c895fff279b71b0dbbad6647181b
md5sum = 605c1f62f93bbb77bb5f3b485882d4f2
url = ${:_profile_base_location_}/instance.cfg.in
output = ${buildout:directory}/instance.cfg
mode = 0644
......@@ -107,7 +107,7 @@ mode = 0644
[template-runTestSuite]
recipe = slapos.recipe.template
url = ${:_profile_base_location_}/runTestSuite.in
md5sum = 88e820d30b36ecca9b45242ce4a52039
md5sum = e34e5242b3dd5d8d137c872b7b63573a
output = ${buildout:directory}/runTestSuite.in
mode = 0644
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment