How do I include the setup method in python-appium base page? - python

I am just a beginner when it comes to python or coding in general. I'm trying to setup an automation framework using python-appium and the page object model. My question is, How do I include the setup method into my base page? When I call the method from my test script it says 'driver' is unresolved and throws an exception. I know I am just missing something simple but my google-fu has failed me and now I have posted here.
Here is my setup method:
def setUp(self):
"Setup for the test"
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '6.0.1'
desired_caps['deviceName'] = '05157df532e5e40e'
# Returns abs path relative to this file and not cwd
desired_caps['app'] = os.path.abspath(
os.path.join(os.path.dirname(__file__),
'/Users/tyler/Desktop/Instasize_20172109_3.9.9_118_google.apk'))
desired_caps['appPackage'] = 'com.jsdev.instasize'
desired_caps['appActivity'] = '.activities.MainActivity'
self.driver = webdriver.Remote('http://localhost:4723/wd/hub',
desired_caps)
I want to call this method to all my tests or a variation of it depending on the device being used. Here is how I am trying to call it from my base page:
def driverSetup(self):
driverSetup = DriverBuilderAndroid(driver)
driverSetup.setUp()
All of my import statements are present. Let me know if there is any other info you need. If you could refer to a python appium POM tutorial that would be much appreciated as well. This is my first post on stackoverflow.

I created a separate python file called driverBuilder with my setup shown above. I then import it into each of my test files and call the method like this:
from DriverBuilder import DriverBuilder """<--class from DriverBuilder file"""
def test(self):
driver = DriverBuilder.driver

Related

Creation of a class instance by reflection in Python does not work

I have the following code:
theModule = locate(<the location of my python script in the file system>)
class_ = getattr(theModule, '<the class of my module>')
myAppli = class_()
But I always have an AttributeError exception when trying to perform the "getattr" method.
My objective was to create a Python class from a file somewhere in the file system, and execute methods on it by reflection without using the class declaration in the Python code.
Example
For example, I have the following python script, let's say that the name of the script file is: myScript.py
import sys
class PythonAppli:
def aMethod(self):
sys.echo('I am here\n')
And I perform this in another script in the same directory:
from pydoc import locate
theModule = locate('myScript.py')
class_ = getattr(theModule, 'pythonAppli')
myAppli = class_()
I have the following exception on the "getattr" line:
AttributeError: class PythonAppli has no attribute 'pythonAppli'
Note that if I add this line before my "getattr" method call:
inspect.getmembers(theModule)
I find 'pythonAppli' in the list of attributes.
I looked on the question about dynamic instanciation on StackOverflow but could not find my error here.
Per MisterMiyagi answer, my mistake was theModule was already my desired class. The following code did work:
from pydoc import locate
theModule = locate('myScript.py')
pythonAppli = theModule()
So it was much more simple that I imagined.

passing a URL to test against with nose testconfig

is there a way to configure test-config so that i can pass a URL in command line i.e. 'nosetests --tc=systest_url test_suit.py'
I need to run my selenium tests against dev and systest environments when performing builds on teamcity. Our team decided to use python for UI tests and Im more a Java guy and I'm tring to figure out how the plugin works it looks like i can store the url in yaml and pass the file to the --tc command but doesn't seem to work
the code i inherited looks like this :
URL = config['test' : 'https://www.google.com', ]
class BaseTestCase(unittest.TestCase, Navigation):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Firefox()
cls.driver.implicitly_wait(5)
cls.driver.maximize_window()
cls.driver.get(URL)
which obviously is not working
There is a plugin for nose, the nosetest-config. You can specify some config file and pass filename to --tc-file arg from nose.
config.ini
[myapp_servers]
main_server = 10.1.1.1
secondary_server = 10.1.1.2
In your test file you can load the config.
test_app.py
from testconfig import config
def test_foo():
main_server = config['myapp_servers']['main_server']
Than, call nose with args
nosetests -s --tc-file example_cfg.ini
As described in docs, you can use other config files type like YAML, JSON or even Python modules.
Using the nose-testconfig --tc option you can override a configuration value. Separate the key from the value using a colon. For example,
nosetests test.py --tc=url:dev.example.com
will make the value available in config['url'].
from testconfig import config
def test_url_is_dev():
assert 'dev' in config['url']

Selenium2Library code completion in PyCharm

I'm experimenting with creating a basic library extension for Robot Framework using Python, and I'm using PyCharm as the editor. For libraries imported directly code completion is working fine, but in this case I'm importing the Selenium2Library indirectly via a method:
def get_current_browser():
browser = BuiltIn().get_library_instance('Selenium2Library')._current_browser()
return browser
Which I call from other methods with something like
driver = get_current_browser()
This successfully grabs the webdriver browser instance from Robot Framework and lets me do as I please, but I don't get code hints when I go to edit a 'driver' variable. Is there way I can get hints in this scenario?
Here's the code in full:
from robot.libraries.BuiltIn import BuiltIn
from Selenium2Library.keywords.keywordgroup import KeywordGroup
import logging
def get_current_browser():
browser = BuiltIn().get_library_instance('Selenium2Library')._current_browser()
return browser
class MyLibrary(KeywordGroup):
def get_title_via_python(self):
driver = get_current_browser()
title = driver.title
logging.warn("checking title %s" % title)
return title
Try adding a docstring to your function to help PyCharm.
from selenium.webdriver import Remote # Remote imported only for code completion
def get_current_browser():
"""
:rtype: Remote
"""
browser = BuiltIn().get_library_instance('Selenium2Library')._current_browser()
return browser
More at http://www.jetbrains.com/pycharm/webhelp/type-hinting-in-pycharm.html

Python Help: Accessing static member variable from another class

I'll do my best to describe the issue I am having. I am building a Python program that is built on multiple classes and uses the unittest framework. In a nutshell, the Main.py file has a "ValidateDriver" class that defines a "driver" variable as an ElementTree type. If I point this directly to the XML file I need to parse, (i.e. driver = ElementTree.parse(rC:\test.xml)) then I can access it from another class. However, in reality I don't have the actual XML file that is passed in from the command-line until you get to the Main function in the ValidateDriver class. So under the ValidateDriver class driver would really be driver = ElementTree and then in the main function I would reassign that variable to ValidateDriver.driver = ElementTree.parse(args.driver). However, this is the crux. When I go to the other class and try to call ValidateDriver.driver I don't have the "findall" method/attribute available. Again, the only way it will work is to do something like: ElementTree.parse(rC:\test.xml)). If I did this in C# it would work, but I am new to Python and this is kicking my butt. Any help/suggestions is appreciated. I've included the code for both classes.
Main Function:
import sys
import argparse
import xml.etree.ElementTree as ElementTree
import unittest
import Tests.TestManufacturer
class ValidateDriver:
driver = ElementTree
def main(argv):
parser = argparse.ArgumentParser(description='Validation.')
parser.add_argument('-d', '--driver', help='Path and file name xml file', required=True)
parser.add_argument('-v', '--verbosity',
help='Verbosity for test output. 1 for terse, 2 for verbose. Default is verbose',
default=2, type=int)
#args = parser.parse_args()
args = r'C:\test.c4i'
#print ("Validate Driver: %s" % args.driver)
#print ("Verbosity Level: %s" % args.verbosity)
ValidateDriver.driver = ElementTree.parse(r'C:\test.c4i')
loader = unittest.TestLoader()
suite = loader.loadTestsFromModule(Tests.TestManufacturer)
runner = unittest.TextTestRunner(verbosity=2) # TODO Remove this...
# TODO Uncomment this...
runner = unittest.TextTestRunner(verbosity=args.verbosity)
result = runner.run(suite)
if __name__ == "__main__":
main(sys.argv[1:])
Other Class, Test Manufacturer:
import unittest
import Main
manufacturer = ['']
class Tests(unittest.TestCase):
# Test to see if Manufacturer exists.
def test_manufacturer_exists(self):
for m in Main.ValidateDriver.driver.findall('./manufacturer'):
print m.text
Producing the following error:
C:\Python27\python.exe C:\Users\test\PycharmProjects\Validator\Main.py
Traceback (most recent call last):
File "C:\Users\test\PycharmProjects\Validator\Main.py", line 22, in <module>
class ValidateDriver:
File "C:\Users\test\PycharmProjects\Validator\Main.py", line 65, in ValidateDriver
main(sys.argv[1:])
File "C:\Users\test\PycharmProjects\Validator\Main.py", line 36, in main
ValidateDriver.driver = ElementTree.parse(r'C:\test.c4i')
NameError: global name 'ValidateDriver' is not defined
Process finished with exit code 1
The main problem seems to be that your main script is wrapped in a class. There's really no reason for this, and is quite confusing.
if __name__ == "__main__":
main_object = ValidateDriver()
main_object.main(sys.argv[1:])
This should go outside the class definition
This has nothing to do with "findall" being available. The issue is that the class itself hasn't yet been completely declared at the time you try to access it. In python, the file is read top to bottom. For example, this is not allowed:
if __name__ == "__main__":
f()
def f():
...
The call to f must happen at the bottom of the file after it is declared.
What you're doing with ValidateDriver is similar, because the class isn't defined until the statements directly in its body are executed (this is different from functions, whose bodies of course aren't executed until they are called). You call main(sys.argv[1:]) inside the class body, which in turn tries to access ValidateDriver.driver, which doesn't exist yet.
Preferably, the main function, as well as the code which calls it, should be outside the class. As far as I can tell, the class doesn't need to exist at all (this isn't C# or Java -- you can put code directly at the module level without a class container). If you insist on putting it in a class as a static method, it must be defined as a class method:
#classmethod
def main(cls, argv):
...
which can then be called (outside the class definition) like:
ValidateDriver.main(sys.argv[1:])
But I stress that this is non-standard and should not be necessary.

Passing own arguments to ryu proxy app

I am developing ryu app. The app is basically a python script. The ryu apps are invoked by ryu-manager like this
ryu-manager {filename}
There are certain parameters that are taken by ryu-manager. I want to know if there is a way i could pass arguments to my file?
argparse module of python to parse command line options is there but am not sure it will work as all arguments I provide are used by ryu-manager not my script.
Any help would be appreciated.
I haven't tried this, but:
"Ryu currently uses oslo.config.cfg for command-line parsing.
(ryu/contrib/oslo/config).
There are several examples in the tree. ryu/app/tunnel_port_updater.py"
from
http://comments.gmane.org/gmane.network.ryu.devel/2709
see also
https://github.com/osrg/ryu/blob/master/ryu/app/tunnel_port_updater.py
The Ryu 'getting started' page simply suggests:
ryu-manager [--flagfile <path to configuration file>] [generic/application specific options…]
http://www.osrg.net/ryu/_sources/getting_started.txt
Doing so is a 4-step process. I'll show an example where you read parameters and then print them, but you could assign them to variables or do whatever you would like to by referencing this process.
Create a .conf file (e.g. params.conf)
#Example Conf File
[DEFAULT]
param1_int = 42
param2_str = "You read my data :)"
param3_list = 1,2,3
param4_float = 3.14
Add the following code to your __init__ method. I did this to the simple_switch_13.py which comes with ryu:
from ryu import cfg
:
:
class SimpleSwitch13(app_manager.RyuApp):
def __init__(self, *args, **kwargs):
super(SimpleSwitch13, self).__init__(*args, **kwargs)
:
CONF = cfg.CONF
CONF.register_opts([
cfg.IntOpt('param1_int', default=0, help = ('The ultimate answer')),
cfg.StrOpt('param2_str', default='default', help = ('A string')),
cfg.ListOpt('param3_list', default = None, help = ('A list of numbers')),
cfg.FloatOpt('param4_float', default = 0.0, help = ('Pi? Yummy.'))])
print 'param1_int = {}'.format(CONF.param1_int))
print 'param2_str = {}'.format(CONF.param2_str))
print 'param3_list = {}'.format(CONF.param3_list))
print 'param4_float = {}'.format(CONF.param4_float))
Run Script
ryu-manager paramtest.py --config-file [PATH/TO/FILE/params.conf]
Profit
I referenced the following when putting together my answer, they can provide more detail (such as the oslo.config stuff, which I had never heard of prior to running into this issue).
More info on oslo.config: http://www.giantflyingsaucer.com/blog/?p=4822
Ryu email chain on this issue: https://sourceforge.net/p/ryu/mailman/message/33410077/
I have not found a way to pass arguments to a ryu controller. One way that I have used to get around this is to pass arguments as an environment variable. For example, I have a program which invokes ryu-manager and needs to pass a parameter to the app. I do this as follows: ARG=value ryu-manager app.py

Categories

Resources