Python: command line argument not passed in the same way as string encoded strings

I am working on some Selenium scripts to test sites across different devices, browsers and platforms. I can get the scripts to work using the same code, except for two lines where I define the url of the command executors and the browser capabilities. I am trying to build one script where I can define these lines using command line arguments.

Here's my code:

from selenium import webdriver
import time
import sys
import getopt
def main(argv):
    #define desired browser capabilities
    desktopCapabilities = {'browserName': 'chrome'} #change browserName to: 'firefox' 'chrome' 'safari' 'internet explorer'
    iosCapabilities = {'platformName': 'iOS' ,'platformVersion': '8.1' ,'deviceName': 'iPad Air','browserName': 'Safari'}
    androidCapabilities = {'chromeOptions': {'androidPackage': 'com.android.chrome'}}
    # Establish the command executor URL
    desktopExecutor = 'http://127.0.0.1:4444/wd/hub'
    iosExecutor = 'http://127.0.0.1:4723/wd/hub'
    androidExecutor = 'http://127.0.0.1:9515'

    cmdExecutor = desktopExecutor
    browserCapabilities = desktopCapabilities
    try:
      opts, args = getopt.getopt(argv,"he:c:",["executor=","capabilities="])
    except getopt.GetoptError:
      print 'test.py -e <executor> -c <capabilities>'
      sys.exit(2)
    for opt, arg in opts:
      if opt == '-h':
         print 'test.py -e <executor> -c <capabilities>'
         sys.exit()
      elif opt in ("-e", "--executor"):
         cmdExecutor = arg
      elif opt in ("-c", "--capabilities"):
         browserCapabilities = arg

    print 'Command executor is:', cmdExecutor
    print 'Desired capabilities are:', browserCapabilities
    driver = webdriver.Remote(command_executor=cmdExecutor, desired_capabilities=browserCapabilities)
    driver.get("http://google.com")
    time.sleep(5)
    driver.quit()
if __name__ == "__main__":
   main(sys.argv[1:])

      

This code works as expected if I don't add any arguments via the command line. It also works if I run it with:

python test.py -e 'http://127.0.0.1:4444/wd/hub'

      

It breaks if I run it using the following command, because -c is not passed as a dictionary:

python test.py -e 'http://127.0.0.1:4444/wd/hub' -c {'browserName': 'firefox'}

      

How can I get this to run this with:

python test.py -e iosExecutor -c iosCapabilities

      

Here's the output I get when I run the command mentioned above:

 python my_script.py -e iosExecutor --capabilities iosCapabilities
Command executor is: iosExecutor
Desired capabilities are: iosCapabilities
Traceback (most recent call last):
  File "my_script.py", line 38, in <module>
    main(sys.argv[1:])
  File "my_script.py", line 33, in main
    driver = webdriver.Remote(command_executor=cmdExecutor, desired_capabilities=browserCapabilities)
  File "/Library/Python/2.7/site-packages/selenium/webdriver/remote/webdriver.py", line 62, in __init__
    raise WebDriverException("Desired Capabilities must be a dictionary")
selenium.common.exceptions.WebDriverException: Message: Desired Capabilities must be a dictionary

      

It basically works as if I were going through line 33 like this:

driver = webdriver.Remote(command_executor="iosExecutor", desired_capabilities="iosCapabilities")

      

It also works if I hardcode lines 15 and 16 with "iosExecutor" and "iosCapabilites", so this tells me how I am passing information from the CLI.

Any advice would be great. I'm new to this (programming) so I'm guessing there might be a better way to do this, but Google hasn't figured it out for me.

+3


source to share


1 answer


Using argparse

will simplify the situation. For capabilities

you can use json.loads

or ast.literal_eval

as type , as was done here, for example:

As for executor

, either pass the url as a string or define a user-friendly mapping like:

EXECUTORS = {
    'desktop': 'http://127.0.0.1:4444/wd/hub',
    'ios': 'http://127.0.0.1:4723/wd/hub',
    'android': 'http://127.0.0.1:9515'
}

      

This is what the code looks like at the end:



import ast
import time
import argparse

from selenium import webdriver


EXECUTORS = {
    'desktop': 'http://127.0.0.1:4444/wd/hub',
    'ios': 'http://127.0.0.1:4723/wd/hub',
    'android': 'http://127.0.0.1:9515'
}

parser = argparse.ArgumentParser(description='My program.')
parser.add_argument('-c', '--capabilities', type=ast.literal_eval)
parser.add_argument('-e', '--executor', type=str, choices=EXECUTORS)

args = parser.parse_args()

driver = webdriver.Remote(command_executor=EXECUTORS[args.executor], desired_capabilities=args.capabilities)
driver.get("http://google.com")
time.sleep(5)
driver.quit()

      

An example script works:

$ python test.py -e android -c "{'chromeOptions': {'androidPackage': 'com.android.chrome'}}"
$ python test.py -e ios -c "{'platformName': 'iOS' ,'platformVersion': '8.1' ,'deviceName': 'iPad Air','browserName': 'Safari'}" 
$ python test.py -e desktop -c "{'browserName': 'chrome'}"

      

And, as a bonus, you get magic-generated built-in help argparse

:

$ python test.py --help
usage: test.py [-h] [-c CAPABILITIES] [-e {android,ios,desktop}]

My program.

optional arguments:
  -h, --help            show this help message and exit
  -c CAPABILITIES, --capabilities CAPABILITIES
  -e {android,ios,desktop}, --executor {android,ios,desktop}

      

+4


source







All Articles