I'm trying to generate a screenshot for the allure report using the pytest_runtest_makereport hook but get stuck because 'if' statement=false in this block of code:
if 'setup' in item.fixturenames:
web_driver = item.funcargs['setup']
else:
print('Fail to take screenshot.No setup fixture found')
Here is conftest.py:
#pytest.fixture(scope='function')
def get_webdriver(get_edge_options):
options = get_edge_options
print("Current working dir : %s" % os.getcwd())
s = Service('D:\mmanager\msedgedriver.exe')
driver = webdriver.Edge(service=s, options=options)
# driver.delete_all_cookies()
return driver
#pytest.fixture(scope='function') # function means run each test in new browser session
def setup(request, get_webdriver):
driver = get_webdriver
if request.cls is not None:
request.cls.driver = driver
driver.get(FCC_HOME)
yield driver
driver.quit()
# Shared Given Steps
#given('the MM3-0 login page is displayed', target_fixture='MM_Login_page')
def MM_Login_page(setup):
pass
#pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
if (rep.when == 'call' or rep.when == 'setup') and (rep.failed or rep.skipped):
try:
if 'setup' in item.fixturenames:
web_driver = item.funcargs['setup']
else:
print('Fail to take screenshot.No setup fixture found')
return
allure.attach(
web_driver.get_screenshot_as_png(),
name='!! Screenshot Captured !!',
attachment_type=allure.attachment_type.PNG)
except Exception as e:
print('Fail to take screen-shot: {}'.format(e))
Related
I'm currently using Python and Selenium to loop my server for specific tasks to complete, I have tried to do 2 things, to speed up the process they are:
To use options.add_argument(f"user-data-dir={script_directory}\\profile") in the Chrome driver initiasation to avoid having to log in all the time.
To try and reuse the same browser window instead of closing and then re-opening the browser all the time.
Code:
#!/usr/bin/env python
import pathlib
import time
import urllib.parse
import requests
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
USER = "..."
PASS = "..."
def upload_to_server(link, redirect, unique_hash):
try:
requests.get(
"https://www.example.com/crons.php?cronUploadToServer=1&link={0}&redirect={1}&hash={2}".format(link,
redirect,
unique_hash))
except Exception as e:
print(e)
def download_from_server():
try:
server = requests.get("https://www.example.com/crons.php?cronDownloadFromServer=1")
return server.text.strip()
except Exception as e:
print(e)
# tear down chrome.
def tear_down(_driver):
_driver.quit()
_driver.close()
def check_for_tasks():
if download_from_server() == "NO_TASKS":
print("--> NO TASKS")
else:
# init the chrome driver.
def init_driver(using_linux, proxy):
script_directory = pathlib.Path().absolute()
try:
options = Options()
options.headless = False
options.add_argument('start-maximized')
options.add_argument('--disable-popup-blocking')
options.add_argument('--disable-notifications')
options.add_argument('--log-level=3')
options.add_argument('--ignore-certificate-errors')
options.add_argument('--ignore-ssl-errors')
options.add_argument(f"user-data-dir={script_directory}\\profile")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option("detach", True)
prefs = {'profile.default_content_setting_values.notifications': 2}
options.add_experimental_option('prefs', prefs)
if proxy == "0.0.0.0:0":
print("--> PROXY DISABLED ...")
else:
print("--> PROXY: " + str(proxy) + " ...")
options.add_argument('--proxy-server=%s' % proxy)
if using_linux:
return webdriver.Chrome(options=options)
else:
return webdriver.Chrome(options=options)
except Exception as e:
print(e)
# create session.
driver = init_driver(False, "0.0.0.0:00")
# starting URL.
driver.get('https://www.example.com/logon')
# click recorded.
def topcashback_click(_driver):
try:
_driver.get('https://www.example.com/Earn.aspx?mpurl=shein&mpID=17233')
if "redirect.aspx?mpurl=shein" in _driver.current_url:
return _driver.current_url
else:
return False
except Exception as e:
print(e)
# already logged in check.
if ">Account</span>" in driver.page_source:
print("--> LOGGED IN (ALREADY) ...")
driver.get('https://www.SITE.CO.UK/Earn.aspx?mpurl=shein&mpID=17233')
try:
server = download_from_server()
data_from_server = server.split('|')
link = topcashback_click(driver)
print("--> LINK --> " + link)
time.sleep(4)
if link != driver.current_url:
print("--> LINK (REDIRECT) --> " + driver.current_url)
upload_to_server(urllib.parse.quote_plus(link),
urllib.parse.quote_plus(
driver.current_url.replace('https://www.example.com', data_from_server[0])),
data_from_server[1])
# print(driver.current_url.replace('https://www.example.com', data_from_server[0]))
print("--> LINK UPLOADED TO THE DB ...")
# tear_down(driver)
except Exception as e:
print(e)
else:
# TopCashBack login for the first time.
def topcashback_login(_driver):
_driver.get('https://www.example.com/logon')
# small sleep to let the page load.
time.sleep(1)
_driver.find_element(By.XPATH, '//*[#id="txtEmail"]').send_keys(USER)
time.sleep(1)
_driver.find_element(By.XPATH, '//*[#id="loginPasswordInput"]').send_keys(PASS)
time.sleep(1)
_driver.find_element(By.XPATH, '//*[#id="Loginbtn"]').click()
time.sleep(5)
if ">Account</span>" in _driver.page_source:
return True
else:
return False
def topcashback_click(_driver):
try:
_driver.get('https://www.SITE.CO.UK/Earn.aspx?mpurl=shein&mpID=17233')
if "redirect.aspx?mpurl=shein" in _driver.current_url:
return _driver.current_url
else:
return False
except Exception as e:
print(e)
if topcashback_login(driver):
try:
print("--> LOGGED IN ...")
server = download_from_server()
data_from_server = server.split('|')
link = topcashback_click(driver)
print("--> LINK --> " + link)
time.sleep(4)
if link != driver.current_url:
print("--> LINK (REDIRECT) --> " + driver.current_url)
upload_to_server(urllib.parse.quote_plus(link),
urllib.parse.quote_plus(
driver.current_url.replace('https://www.example.com',
data_from_server[0])),
data_from_server[1])
# print(driver.current_url.replace('https://www.example.com', data_from_server[0]))
print("--> LINK UPLOADED TO THE DB ...")
# tear_down(driver)
except Exception as e:
print(e)
else:
print("--> ERROR --> DEBUG TIME ...")
tear_down(driver)
if __name__ == "__main__":
while True:
check_for_tasks()
time.sleep(2)
It's the 2nd one I'm having trouble with, currently, with my code, I'm getting the error:
driver.get('https://www.example.com/logon')
AttributeError: 'NoneType' object has no attribute 'get'
I think this is because I'm not connecting the first browser window, instead it's opening a new one which fails with the error above straight away.
Is there possibly a way to keep the first browser open and reuse it? any help would be appreciated.
The code runs in a conftest file, when the test falls the screenshots file is saved in the test folder but can it be changed that the image will be saved in a new folder called screenshots?
Thanks
#pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
"""
Extends the PyTest Plugin to take and embed screenshot in html report, whenever test fails.
:param item:
"""
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call' or report.when == "setup":
xfail = hasattr(report, 'wasxfail')
if (report.skipped and xfail) or (report.failed and not xfail):
file_name = report.nodeid.replace("::", "_") + ".png"
_capture_screenshot(file_name)
if file_name:
html = '<div><img src="%s" alt="screenshot" style="width:304px;height:228px;" ' \
'onclick="window.open(this.src)" align="right"/></div>' % file_name
extra.append(pytest_html.extras.html(html))
report.extra = extra
def _capture_screenshot(name):
driver.get_screenshot_as_file(name)
#pytest.fixture(scope='session', autouse=True)
def browser():
global driver
if driver is None:
driver = webdriver.Chrome()
return driver
I have two files one is Login_test.py and the other is Financial_Account_Balance.py. When I run the Login file, it works but I want after the system Login, it should check the Financial Account. I keep getting error when I instantiate the Class in the Financial Account Script.
Object has no attribute 'driver'
Below is my code for both files
Login_test
import unittest
from selenium import webdriver
import time
class LoginForm(unittest.TestCase):
def __init__(self, driver = None):
#super().__init__(driver)
if driver is not None:
self.driver = driver
else:
self.setUp()
def setUp(self):
self.driver = webdriver.Chrome(executable_path=r"..\browser\chromedriver.exe")
print("Running Set Up method")
print(self.driver)
self.test_result = None
def test_Login(self):
# We wrap this all in a try/except so we can set pass/fail at the end
try:
# load the page url
print('Loading Url')
self.driver.get('http://localhost:4200/')
# maximize the window
#print('Maximizing window')
self.driver.maximize_window()
# we'll start the login process by entering our username
print('Entering username:')
self.driver.find_element_by_name('username').send_keys('mobile#******.com')
# then by entering our password
print('Entering password:')
self.driver.find_element_by_id('pass').send_keys('*****')
# now we'll click the login button
print('Logging in')
self.driver.find_element_by_class_name("submit").click()
time.sleep(25)
self.test_result = 'pass'
except AssertionError as e:
# log the error message
self.test_result = 'fail'
raise
"""
def tearDown(self):
print("Done with session")
self.driver.quit()
"""
if __name__ == '__main__':
unittest.main()
Financial Account File
from Unit_Test_Files.Login_test import *
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
import time
import logging
import unittest
class FinancialAccountBalance:
#logf = open("Financial_Account_Balance_exception.log", "w")
def __init__(self, driver = None):
if driver is not None:
self.driver = driver
else:
print('Financial Account Balance Testing Started...')
self.test_finacial()
def setUp(self):
print(self.driver)
print("setup method running")
self.test_finacial()
def test_finacial(self):
try:
print(self.driver)
self.driver.find_element_by_xpath(
'/html/body/chankya-app/chankya-layout/div/ng-sidebar-container/div/div/section/div/div[2]/app-home/div/div/div/div/div[2]/div/input').send_keys(
'Financial Account Balance')
time.sleep(2)
self.driver.find_element_by_xpath(
'/html/body/chankya-app/chankya-layout/div/ng-sidebar-container/div/div/section/div/div[2]/app-home/div/div/div/div/div[2]/div/input').send_keys(
Keys.ENTER)
time.sleep(2)
WebDriverWait(self.driver, 10).until(
EC.presence_of_all_elements_located(
(By.XPATH, '//html/body/chankya-app/chankya-layout/div/ng-sidebar-container'
'/div/div/section/div/div[2]/app-home/div/div/div/div/div[4]'
'/div/div/table/tbody/tr')))
result = self.driver.find_element_by_xpath(
'(/html/body/chankya-app/chankya-layout/div/ng-sidebar-container/div/div/section/div/div[2]/app-home/div/div/div/div/div[4]/div/div/table/tbody/tr)[1]')
result.click()
time.sleep(15)
logging.basicConfig(filename='Financial_Account_Balance.log', level=logging.INFO, filemode='w',
format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p ')
logging.info('Date and Time \nReport: Financial Account Balance Automation Test is Successful!!! \n')
print('Financial Account Balance Automation Test is Successful!!!')
except AssertionError as e:
# log the error message
self.test_result = 'fail'
raise
def test_verify(self):
lf = LoginForm()
lf.test_Login()
self.test_finacial()
if __name__ == '__main__':
fa = FinancialAccountBalance()
fa.test_verify()
Error I get when I run the Financial Account file
"C:\Users\Apollo Universe IDS\.virtualenvs\test-cM_nBYrn\Scripts\python.exe" C:/Users/Public/Documents/test/Financial_Module/Financial_Account_Balance.py
Financial Account Balance Testing Started...
Traceback (most recent call last):
File "C:/Users/Public/Documents/test/Financial_Module/Financial_Account_Balance.py", line 68, in <module>
fa = FinancialAccountBalance()
File "C:/Users/Public/Documents/test/Financial_Module/Financial_Account_Balance.py", line 21, in __init__
self.test_finacial()
File "C:/Users/Public/Documents/test/Financial_Module/Financial_Account_Balance.py", line 30, in test_finacial
print(self.driver)
AttributeError: 'FinancialAccountBalance' object has no attribute 'driver'
def __init__(self, driver = None):
if driver is not None:
self.driver = driver
else:
print('Financial Account Balance Testing Started...')
self.test_finacial()
if driver is none , you are not creating any self.driver . so that class will not have any instance variable driver in that case
fix:
class FinancialAccountBalance:
#logf = open("Financial_Account_Balance_exception.log", "w")
def __init__(self, driver = None):
if driver is not None:
self.driver = driver
else:
print('Financial Account Balance Testing Started...')
self.setUp()
def setUp(self):
self.driver = webdriver.Chrome(executable_path=r"..\browser\chromedriver.exe")
print(self.driver)
print("setup method running")
self.test_finacial()
I have a table with multiple pages. I want to select say 5 elements from the table and click on the checkbox corresponding to those at a time. How is that possible through selenium python automation
def __init__(self, env):
self.driver = webdriver.Firefox()
self.driver.maximize_window()
if env == 'Staging':
self.driver.get("https://serviceconsole-stg.tivo.com/serviceconsole/login.action")
elif env == 'QE':
self.driver.get("http://serviceconsolese01.tivo.com:9090/serviceconsole")
else:
print "Environment is not available", env
print "\n Supported Environments are Staging and QE"
self.driver.quit()
raise SystemExit("Program Exited")
with open('config.json','r') as user_credentials:
config = json.load(user_credentials)
self.driver.find_element_by_id('username').send_keys(config['user']['name'])
self.driver.find_element_by_id('password').send_keys(config['user']['password'])
self.driver.find_element_by_id("signIn").click()
try:
self.driver.find_element_by_xpath('// *[ # id = "loginValidationError"]')
print "Login Not successful"
self.driver.quit()
raise SystemExit("Program Exited")
except NoSuchElementException:
print "Login Successful"
def addnewlinearpackage(self, title, enddate_days_from_today):
try:
# Select Manage
self.driver.find_element_by_xpath("//*[#id='configuration-tab']").click()
# Creating new Linear Package
self.driver.find_element_by_id("linearpublishing").click()
self.driver.find_element_by_id("linpub").click()
self.driver.find_element_by_id("addLinearPackage").click()
self.driver.find_element_by_id("linearpackageTitle").send_keys(title)
self.driver.find_element_by_id('tempPackageId').send_keys(
datetime.strftime(datetime.now(), '%Y%m%d%H%M'))
self.driver.find_element_by_id("inlineLinearPackageCheckbox").click()
start_time = self.driver.find_element_by_id('startDate')
execute = start_time.find_element_by_xpath("*//span[#class='fa fa-calendar']")
self.driver.execute_script("arguments[0].click();", execute)
time.sleep(7)
end_time = self.driver.find_element_by_id('endDate')
end_time.find_element_by_xpath("*//span[#class='fa fa-calendar']").click()
end_date = (datetime.now() + timedelta(days=enddate_days_from_today)).strftime('%m/%d/%Y')
self.driver.find_element_by_xpath("*//td[#data-day='" + end_date + "']").click()
time.sleep(7)
except NoSuchElementException as exp:
print exp
self.driver.quit()
raise SystemExit("Program Exited")
def addlinearservice(self, serviceId):
try:
self.driver.find_element_by_id("linearServiceSection").click()
time.sleep(10)
self.driver.find_element_by_id("publishLinearPackageBtn").click()
time.sleep(30)
self.driver.find_element_by_class_name("sorting_1")
linear_service_found = False
# Searching existing linear service
if linear_service_found == False:
try:# Search in first page
self.driver.find_element_by_xpath(
"/html/body/div[4]/div/div/div[2]/div/div/div/div[2]/div[2]/div/ul/li[9]/a").click()
if self.driver.find_element_by_link_text(serviceId).is_displayed():
self.driver.find_element_by_xpath(
"//a[contains(text(),'" + serviceId + "')]/following::td/input[#type='checkbox']").click()
linear_service_found = True
print "Linear service found"
except NoSuchElementException:
print"No such Element found in page 1"
try:
while linear_service_found == False: # loop to navigate to next page till finding the service ID
try: # Search till last page is reached and next button is disabled
self.driver.find_element_by_xpath(
"// *[#id = 'associatedLinearServicesTable1_next']/../li[#class ='paginate_button next disabled']")
print 'No further Page available to search'
break
except NoSuchElementException:
try:
self.driver.find_element_by_xpath(
'/html/body/div[4]/div/div/div[2]/div/div/div/div[2]/div[2]/div/ul/li[9]/a').click()
if self.driver.find_element_by_link_text(serviceId).is_displayed():
# click the checkbox of Service ID
self.driver.find_element_by_xpath(
"//a[contains(text(),'" + serviceId + "')]/following::td/input[#type='checkbox']").click()
linear_service_found = True
print "Linear Service found"
break
except NoSuchElementException:
print "No such Element found in current page"
except NoSuchElementException:
print"No such Element found"
if linear_service_found == True:
time.sleep(10)
#Click on Save button
self.driver.find_element_by_xpath('/ html / body / div[4] / div / div / div[3] / button[1]').click()
time.sleep(10)
except NoSuchElementException as exp:
print exp
self.driver.quit()
raise SystemExit("Program Exited")
def publish(self):
try:
self.driver.find_element_by_xpath('//button[contains(text(), "Publish")]').click()
time.sleep(5)
self.driver.find_element_by_xpath('//*[#id="confirmDialogOk"]').click()
time.sleep(10)
try:
self.driver.find_element_by_xpath('//*[#id="appSuccessMsg"]')
print("Linear Package Published Successfully")
except NoSuchElementException:
print ("Linear Package NOT PUBLISHED.. check the Error Message in Service console webpage")
time.sleep(60)
self.driver.quit()
raise SystemExit("Program Exited")
except NoSuchElementException as exp:
print exp
self.driver.quit()
raise SystemExit("Program Exited")
def exit(self):
print("Exiting.....")
time.sleep(5)
self.driver.quit()
Please find the full code. This code works only for selecting one element. I have to select multiple elements.
image
If the checkboxes have a common locator, you can use find_elements_by_xpath instead of find_element_by_xpath. This will return a list of WebElements, which you can then iterate over to click the boxes.
I am scrapping a web site, but sometimes the laptop lost the connection, and I got (obviously) a requests.exceptions.ConnectionError. Which is the right (or most elegant?) way of recover from this error? I mean: I don't want the program to stop, but retry the connection, maybe some seconds later? This is my code, but I got the feeling is not correct:
def make_soup(session,url):
try:
n = randint(1, MAX_NAPTIME)
sleep(n)
response = session.get(url)
except requests.exceptions.ConnectionError as req_ce:
error_msg = req_ce.args[0].reason.strerror
print "Error: %s con la url %s" % (eror_msg, url)
session = logout(session)
n = randint(MIN_SLEEPTIME, MAX_SLEEPTIME)
sleep(n)
session = login(session)
response = session.get(url)
soup = BeautifulSoup(response.text)
return soup
Any ideas?
Note that I need a session to scrap this pages, so, I think that the login (i.e. login again to the site, after a logout) could be cause troubles
So why not something like
import requests
import time
def retry(cooloff=5, exc_type=None):
if not exc_type:
exc_type = [requests.exceptions.ConnectionError]
def real_decorator(function):
def wrapper(*args, **kwargs):
while True:
try:
return function(*args, **kwargs)
except Exception as e:
if e.__class__ in exc_type:
print "failed (?)"
time.sleep(cooloff)
else:
raise e
return wrapper
return real_decorator
Which is a decorator that allows you to call any function until it succeeds. e.g.
#retry(exc_type=[ZeroDivisionError])
def test():
return 1/0
print test()
Which will just print "failed (y)" every 5 seconds until the end of time (or until the laws of math change)
Is it really needed to logout and relogin into your session? I'd just retry the connection the same way:
def make_soup(session,url):
success = False
response = None
for attempt in range(1, MAXTRIES):
try:
response = session.get(url)
# If session.get succeeded, we break out of the
# for loop after setting a success flag
success = True
break
except requests.exceptions.ConnectionError as req_ce:
error_msg = req_ce.args[0].reason.strerror
print "Error: %s con la url %s" % (error_msg, url)
print " Attempt %s of %s" % (attempt, MAXTRIES)
sleep(randint(MIN_SLEEPTIME, MAX_SLEEPTIME))
# Figure out if we were successful.
# Note it may not be needed to have a flag, you can maybe just
# check the value of response here.
if not success:
print "Couldn't get it after retrying many times"
return None
#Once we get here, we know we got a good response
soup = BeautifulSoup(response.text)
return soup