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): ...@@ -58,6 +58,7 @@ class Recipe(GenericBaseRecipe):
"\npath_list = %s" % ",".join(software_path_list) "\npath_list = %s" % ",".join(software_path_list)
CONFIG['computer_id'] = self.buildout['slap-connection']['computer-id'] CONFIG['computer_id'] = self.buildout['slap-connection']['computer-id']
CONFIG['server_url'] = self.buildout['slap-connection']['server-url'] CONFIG['server_url'] = self.buildout['slap-connection']['server-url']
CONFIG['frontend_url'] = self.buildout['testnode-frontend']['connection-secure_access']
configuration_file = self.createFile( configuration_file = self.createFile(
self.options['configuration-file'], self.options['configuration-file'],
self.substituteTemplate( self.substituteTemplate(
......
...@@ -18,6 +18,7 @@ httpd_port = %(httpd_port)s ...@@ -18,6 +18,7 @@ httpd_port = %(httpd_port)s
httpd_software_access_port = %(httpd_software_access_port)s httpd_software_access_port = %(httpd_software_access_port)s
computer_id = %(computer_id)s computer_id = %(computer_id)s
server_url = %(server_url)s server_url = %(server_url)s
frontend_url = %(frontend_url)s
# Binaries # Binaries
git_binary = %(git_binary)s git_binary = %(git_binary)s
......
...@@ -76,8 +76,7 @@ SSLProxyEngine On ...@@ -76,8 +76,7 @@ SSLProxyEngine On
Listen [%(ip)s]:%(software_access_port)s Listen [%(ip)s]:%(software_access_port)s
<VirtualHost *:%(software_access_port)s> <VirtualHost *:%(software_access_port)s>
SSLEngine on SSLEngine on
RewriteRule (.*) http://[%(ip)s]:%(software_access_port)s/VirtualHostBase/https/[%(ip)s]:%(software_access_port)s/VirtualHostRoot/$1 [L,P] DocumentRoot "%(testnode_srv_directory)s"
DocumentRoot "%(testnode_software_directory)s"
<Directory /> <Directory />
Options FollowSymLinks Options FollowSymLinks
IndexOptions FancyIndexing IndexOptions FancyIndexing
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
parts = parts =
nginx-service nginx-service
runTestSuite-instance runTestSuite-instance
eggs-directory = ${buildout:eggs-directory} eggs-directory = ${buildout:eggs-directory}
develop-eggs-directory = ${buildout:develop-eggs-directory} develop-eggs-directory = ${buildout:develop-eggs-directory}
offline = true offline = true
...@@ -36,6 +35,7 @@ framebuffer = $${:srv}/framebuffer ...@@ -36,6 +35,7 @@ framebuffer = $${:srv}/framebuffer
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${template-runTestSuite:output} url = ${template-runTestSuite:output}
output = $${directory:bin}/runTestSuite output = $${directory:bin}/runTestSuite
buildout-directory = $${buildout:directory}
mode = 0700 mode = 0700
[firefox-instance] [firefox-instance]
...@@ -76,7 +76,7 @@ output = $${directory:etc}/nginx.cfg ...@@ -76,7 +76,7 @@ output = $${directory:etc}/nginx.cfg
mode = 0600 mode = 0600
access_log = $${directory:log}/nginx-access.log access_log = $${directory:log}/nginx-access.log
error_log = $${directory:log}/nginx-error.log error_log = $${directory:log}/nginx-error.log
ip = $${instance-parameter:ipv6-random} ip = $${instance-parameters:ipv6-random}
port = 9443 port = 9443
ssl_key = $${directory:ssl}/nginx.key ssl_key = $${directory:ssl}/nginx.key
ssl_csr = $${directory:ssl}/nginx.csr ssl_csr = $${directory:ssl}/nginx.csr
...@@ -85,7 +85,7 @@ ssl_crt = $${directory:ssl}/nginx.crt ...@@ -85,7 +85,7 @@ ssl_crt = $${directory:ssl}/nginx.crt
################################# #################################
# SlapOS service # SlapOS service
################################# #################################
[instance-parameter] [instance-parameters]
recipe = slapos.cookbook:slapconfiguration recipe = slapos.cookbook:slapconfiguration
computer = $${slap_connection:computer_id} computer = $${slap_connection:computer_id}
partition = $${slap_connection:partition_id} partition = $${slap_connection:partition_id}
......
...@@ -31,9 +31,33 @@ def main(): ...@@ -31,9 +31,33 @@ def main():
parser.add_argument('--node_quantity', help='ignored', type=int) parser.add_argument('--node_quantity', help='ignored', type=int)
parser.add_argument('--master_url', parser.add_argument('--master_url',
help='The Url of Master controling many suites') 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() 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: try:
test_suite_title = args.test_suite_title or args.test_suite test_suite_title = args.test_suite_title or args.test_suite
test_suite = args.test_suite test_suite = args.test_suite
...@@ -51,8 +75,27 @@ def main(): ...@@ -51,8 +75,27 @@ def main():
########################## ##########################
# Run all tests # Run all tests
########################## ##########################
firefox_binary = webdriver.firefox.firefox_binary.FirefoxBinary(firefox_path=FIREFOX_EXECUTABLE) if args.target == 'firefox':
browser = webdriver.Firefox(firefox_binary=firefox_binary) 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") agent = browser.execute_script("return navigator.userAgent")
print agent print agent
...@@ -67,7 +110,6 @@ def main(): ...@@ -67,7 +110,6 @@ def main():
body = etree.fromstring(browser.page_source.encode('UTF-8'), html_parser) body = etree.fromstring(browser.page_source.encode('UTF-8'), html_parser)
browser.title.encode('UTF-8') 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()')) print ' '.join(body.xpath('//*[@id="qunit-testresult"]//text()'))
...@@ -99,7 +141,7 @@ def main(): ...@@ -99,7 +141,7 @@ def main():
node_title = args.test_node_title, node_title = args.test_node_title,
test_title = test_suite_title, test_title = test_suite_title,
project_title = args.project_title) project_title = args.project_title)
if test_result is None: if test_result is None or not hasattr(args, 'master_url'):
return return
# report test results # report test results
while 1: while 1:
......
...@@ -25,7 +25,7 @@ parts = ...@@ -25,7 +25,7 @@ parts =
[instance] [instance]
recipe = slapos.recipe.template recipe = slapos.recipe.template
md5sum = 25a9c895fff279b71b0dbbad6647181b md5sum = 605c1f62f93bbb77bb5f3b485882d4f2
url = ${:_profile_base_location_}/instance.cfg.in url = ${:_profile_base_location_}/instance.cfg.in
output = ${buildout:directory}/instance.cfg output = ${buildout:directory}/instance.cfg
mode = 0644 mode = 0644
...@@ -107,7 +107,7 @@ mode = 0644 ...@@ -107,7 +107,7 @@ mode = 0644
[template-runTestSuite] [template-runTestSuite]
recipe = slapos.recipe.template recipe = slapos.recipe.template
url = ${:_profile_base_location_}/runTestSuite.in url = ${:_profile_base_location_}/runTestSuite.in
md5sum = 88e820d30b36ecca9b45242ce4a52039 md5sum = e34e5242b3dd5d8d137c872b7b63573a
output = ${buildout:directory}/runTestSuite.in output = ${buildout:directory}/runTestSuite.in
mode = 0644 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