I have feature file from where I am trying to get the email :
Scenario: Login to website
Given I navigate to Login page
When I click on login button
Then I redirected to login page
Then I enter valid "<Email>"
| Email |
| test |
When I click on Submit
I have below code in LoginPage.py :
from Base.BasePage import BasePage
from Base.WebDriverActions import Seleniumdriver
class LoginPage():
instance = None
#classmethod
def get_instance(cls):
if cls.instance is None:
cls.instance = LoginPage()
return cls.instance
def __init__(self):
self.driver = BasePage.get_driver()
def enterEmail(self, email):
self.driver.implicitly_wait(20)
self.driver.find_element_by_id("login").send_keys(email)
When I call the above method into steps :
from Base.BasePage import BasePage
from behave import step, Given, When, Then
from Pages.LoginPage import loginpage
#Given('I navigate to Login page')
def step_impl(Context):
BasePage.load_BaseURL();
#When('I click on login button')
def step_impl(Context):
loginpage.clickLoginLink()
#Then('I redirected to login page')
def step_impl(self):
print('Verifying user logged in..')
#Then('I enter valid "{Email}"')
def step_impl(Email):
loginpage.enterEmail(Email);
I have below error :
File "..\steps\Steps_Login.py", line 27, in step_impl
loginpage.enterEmail(context, Email);
TypeError: enterEmail() takes 1 positional argument but 3 were given
I tried by adding ** with an argument but no luck.
You are calling enterEmail as loginpage.enterEmail(context, Email) here you are passing arguments to the method as follows
context
Email
Self for class loginpage
Try removing loginpage or context if it works.
Related
Sorry in advance if this question has been asked before. But I am trying to understand if my select class implementation is accurate?
I am using POM for my testing and I have a class called HomePage() and below is the code
class HomePage():
def __init__(self, driver)
self.driver = driver
self.id_that_i_am_using = 'navDropDown1' #this id for dropdown
self.link_text_path = 'Link Text'
# created function for clicking on DropdoWn and it does
def click_on_drop_down(self):
self.driver.find_element(value=self.id_that_i_am_using).click()
# trying to create function for select class
def select_class(self, select, driver):
select = Select()
self.driver.find_element(value=self.id_that_i_am_using).click()
select.select_by_index(1)
The Error I am getting is below:
TypeError: selec_class() missing 2 required positional arguments: 'select' and 'driver'
here is where I am trying to call my select class:
def test_login_valid(self):
driver = self.driver
driver.get("https:www.google.com")
home_page = HomePage(driver)
home_page.click_on_drop_down()
home_page.select_class()
Initially I have def setup() with options to call specific web browsers from another file that have all the information on how to setup the web browser. Remarking out the browser not used.
def setUp(self):
# Choose the Web Browser to test with
operabrowser(self)
# chromebrowser(self)
...
def test_one()
...
def test_two()
...
I am trying to move away from editing the test file each time, I am looking to setup a console input that will call the browser and I have added to def setup().
browser_choice = input ( """Choose your browser
Opera, [Firefox], Chrome or Safari
> """ ).lower ()
if browser_choice == 'opera':
operabrowser()
else chromebrowser()
This works with a single unit test but if there is more than one test in the file it asks each time for a browser choice.
How can I get this option to be asked only once for all tests that will be ran in the test file? I have tried a few other ways of approaching this all unsuccessful.
Tests should be defined as class methods, in your code they appears to be standalone functions not directly related with the class which holds the setUp() method. You just need to modify your code like this:
import unittest
class YouTests(unittest.TestCase):
def setUp(self):
q = 'Choose your browser Opera, [Firefox], Chrome or Safari >'
browser_choice = input (q).lower ()
if browser_choice == 'opera':
operabrowser()
else:
chromebrowser()
def test_one(self):
pass
def test_two(self):
pass
...
If you have multiple classes inheriting from unittest.TestCase and all should use the same browser the browser choice will be best inserted in your global scope. For example:
browser_object = None
...
def operabrowser():
global browser_object
# Init opera object here
def chromebrowser():
global browser_object
# Init chrome object here
...
# Your tests using the browser_object
...
if __name__ == '__main__':
q = 'Choose your browser Opera, [Firefox], Chrome or Safari >'
browser_choice = input (q).lower ()
if browser_choice == 'opera':
operabrowser()
elif browser_choice == 'firefox':
...
else:
chromebrowser()
unittest.main()
Background:
I'm using py.test together with pytest-selenium, now I would like to take a screenshot of page when assertion fails.
Currently I have defined small helper method in my base page object class:
class PageBase(object):
def __init__(self,driver):
self.driver = driver
self.fake = Factory.create()
def screenshot(self,name):
self.driver.save_screenshot(datetime.now().strftime('%Y-%m-%d %H:%M:%S') + 'scr_'+name+'.png')
#contextmanager
def wait_for_page_load(self, timeout=45):
old_page = self.driver.find_element_by_tag_name('html')
yield
WebDriverWait(self.driver, timeout).until(
EC.staleness_of(old_page)
)
The problem is that I would like to make it automated mechanism instead of "manual" usage:
(test class example):
class TestLogin:
#allure.feature('Ability to login into admin panel')
def test_admin_login(self, prepare, page):
print URLMap.admin('test')
driver = prepare
driver.get(URLMap.admin(page))
login_page = LoginPage(driver)
assert login_page.is_page_correct(),'Login page not loaded correctly'
login_page.fill_login_data('testadmin','testadmin')
login_page.click_login_button()
assert login_page.is_user_logged_in(),'User cannot log in with provided credentials'
login_page.screenshot(page+'_logged_in')
How to run certain method for every assertion failure?
I personally haven't used but this might be your solution:
https://pytest.org/latest/example/simple.html#writing-well-integrated-assertion-helpers
Also this could help:
https://pytest.org/latest/assert.html#advanced-assertion-introspection
You have to use hooks.
https://docs.pytest.org/en/latest/example/simple.html#post-process-test-reports-failures
#pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
setattr(item, "rep_" + rep.when, rep)
return rep
#pytest.fixture(autouse=True, scope='session')
def driver(platform, request):
""" some driver setup code """
yield driver
if request.node.rep_call.failed:
try:
driver.get_screenshot_as_png()
except:
pass
driver.quit()
And if you want to attach a screenshot to allure report, simply do:
#pytest.fixture(autouse=True, scope='session')
def driver(platform, request):
""" some driver setup code """
yield driver
if request.node.rep_call.failed:
# Make the screen-shot if test failed:
try:
allure.attach(
driver.get_screenshot_as_png(),
name=request.function.__name__,
attachment_type=allure.attachment_type.PNG)
except:
""" do something """
driver.quit()
I think that screenShotInSelenium page should give you enough information regarding how you create a screenshot when an assert condition is met.
What you are missing is the use of #AfterMethod
Here is the page object file: login.py
from pages.base import BasePage
from config import secrets
from selenium.webdriver.common.keys import Keys
class LoginPage(BasePage):
def __init__(self):
self.webdriver = BasePage.webdriver
port = raw_input("Enter port number: ")
self.url = "http://localhost:" + port
#property
def retrieve_username_field(self):
self.webdriver.find_element_by_name("username")
#property
def retrieve_password_field(self):
self.webdriver.find_element_by_name("password")
def login(self, username=None, password=None):
username = username or secrets.username
password = password or secrets.password
self.retrieve_username_field.send_keys(username)
self.retrieve_password_field.send_keys(password)
self.retrieve_password_field.send_keys(Keys.RETURN)
Here is the base page file: base.py
from selenium import webdriver
class BasePage(object):
webdriver = webdriver.Firefox()
def go(self):
self.webdriver.get(self.url)
Here is the test file: test_login.py
import unittest
from pages.login import LoginPage
login_page = LoginPage()
def setUpModule():
login_page.go()
def tearUpModule():
login_page.logout()
class TestLogin(unittest.TestCase):
def test_login_succeeds_with_valid_credentials(self):
login_page.login()
xpath = "//th[text() = 'Spool Name']"
self.assertIsNotNone(login_page.webdriver.find_element_by_xpath(xpath))
if __name__ == "__main__":
unittest.main()
The problem is that I get this error: http://puu.sh/9JgRd/e61f5acec3.png and I'm not sure why I cannot call login method. I have reference to LoginPage object but failure happens exactly here.
Your problem is not that you can't call login(), but that self.retrieve_username_field returns None and thus does not have a send_keys method.
That's exactly what the error you get is telling you.
I'm new to python with android. I need to write python script.
basically what I want to do is when you click first view, I need to load second view. second view has button, when it press that I need to load third view.
class SimpleAndroidTests(unittest.TestCase):
def setUp(self):
desired_caps = {}
desired_caps['platformName'] = 'Android'
desired_caps['platformVersion'] = '4.2'
desired_caps['deviceName'] = 'Android Emulator'
desired_caps['app'] = PATH(
'mypath/aaa.apk'
)
desired_caps['appPackage'] = 'com.xxxx'
self.driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
def test_find_elementsFirstview(self):
time.sleep(13)
textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
textfields[0].send_keys("first text")
textfields[1].send_keys("second text")
el = self.driver.find_element_by_name("press Login")
el.click()
def test_secondView(self):
time.sleep(10)
textfields = self.driver.find_elements_by_class_name("android.widget.EditText")
textfields[2].send_keys("secondviewinput2")
def tearDown(self):
# end the session
self.driver.quit()
if __name__ == '__main__':
suite = unittest.TestLoader().loadTestsFromTestCase(SimpleAndroidTests)
unittest.TextTestRunner(verbosity=2).run(suite)
ISSUE is it is not entering to the second view. It is re-loding first view again.
please help...
In your code you have a method - setUp(self) - which nose tools interprets as a "test setup" method, meaning it will be run before each test. Since your setUp() method instantiates the webdriver it is reloading your app before each test. Consider moving your driver instantiation to a setUpClass(), which nose tools will run before all tests in the file.
Example test file:
class YourTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
[...runs before all tests...]
def setUp(self):
[...runs before each test...]
def test_test1(self):
[...your tests...]
def tearDown(self):
[...runs after each test...]
#classmethod
def tearDownClass(cls):
[...runs after all tests...]
When an element on an android app is clicked via appium python script, then appium has no control over the expected behavior. It is the app that handles the click. So for example, if there is a Login button and if you do this:
el = self.driver.find_element_by_name("press Login")
el.click()
This click on the element is handled by the app and app will take over the flow from here. It is app that launches the next screen. For example, it could be a form.
Basically, appium python client has control over which UI element to choose, but what that particular UI element will do is up to the app.