str object has no attribute 'get' - python-3.x

I am using unittest example in selenium python
tried google did not get correct solution
from selenium import webdriver
import unittest
#import HtmlTestRunner
class googlesearch(unittest.TestCase):
driver = 'driver'
#classmethod
def setupClass(self):
self.driver = webdriver.Chrome(chrome_options=options)
self.driver.implicitly_wait(10)
self.driver.maximize_window()
def test_search_automationstepbystep(self):
self.driver.get("https://google.com")
self.driver.find_element_by_name("q").send_keys("Automation Step By step")
self.driver.find_element_by_name("btnk").click()
def test_search_naresh(self):
self.driver.get("https://google.com")
self.driver.find_element_by_name("q").send_keys("Naresh")
self.driver.find_element_by_name("btnk").click()
#classmethod
def teardownClass(self):
self.driver.close()
self.driver.quit()
print("Test completed")
if __name__== "__main__":
unittest.main()

As mentioned #Error - Syntactical Remorse , driver is a string due to your first line of code in your class.
If you are planning to access the driver globally make sure to declare the driver as global.

Related

AttributeError: 'HtmlTestResult' object has no attribute '_count_relevant_tb_levels'. Did you mean: '_is_relevant_tb_level'?

import unittest
import HtmlTestRunner
from selenium import webdriver
class Test_OrangeHRM(unittest.TestCase):
#classmethod
def setUpClass(cls):
options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
cls.driver = webdriver.Chrome(options=options)
cls.driver.maximize_window()
def test_HomePage(self):
self.driver.get("https://opensource-demo.orangehrmlive.com/")
self.assertEqual("OrangeHR", self.driver.title, "Webpage Title Is Not Matching")
def test_Login(self):
self.driver.get("https://opensource-demo.orangehrmlive.com/")
self.driver.find_element_by_xpath("//*[#id='txtUsername']").send_keys("Admin")
self.driver.find_element_by_xpath("//*[#id='txtPassword']").send_keys("admin123")
self.driver.find_element_by_xpath("//*[#id='btnLogin']").click()
self.assertEqual("OrangeHRM123", self.driver.title, "Webpage Title Is Not Matching")
#classmethod
def tearDownClass(cls):
cls.driver.quit()
print("Test Completed")
if name=="main":
unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output="C:/Users/HP/PycharmProjects/seleniumPython/Reports"))
This works for me.
Apparently the "_count_relevant_tb_levels" is not available in the newest versions, so you need to go to the source code of the HtmlTestRunner package.
Inside the HtmlTestRunner folder of the package you have installed, look for result.py
Find the "_exc_info_to_string" method of the "HtmlTestResult" class.
Replace these lines:
if exctype is test.failureException:
# Skip assert*() traceback levels
length = self._count_relevant_tb_levels(tb)
msg_lines = traceback.format_exception(exctype, value, tb, length)
with
if exctype is test.failureException:
# Skip assert*() traceback levels
msg_lines = traceback.format_exception(exctype, value, tb)

Send arguments to Pytest fixture for Selenium

Update1:
Thank you for your answer.
It almost solves the problem. If I could be more precise:
How to instantiate the two drivers in 'init_pages', instead of creating two same methods for each driver?
The new snippet as you suggested:
#pytest.mark.usefixtures("driver_init")
class BaseTestFF:
#pytest.fixture
def init_data(self, driver_init):
self.web_driver = driver_init('firefox') #how to inject data via external commands? jenkins?
self.web_driver2 = driver_init('chrome')
#pytest.fixture(autouse=True)
#pytest.mark.usefixtures('init_data')
def init_pages(self, init_data):
#how to instanciate the two drivers here? istead of creating two same methods for each driver
self.login_page = LoginPage(self.web_driver)
self.application_page = ApplicationPage(self.web_driver)
In my selenium project, I would like to be able to send arguments, instead of them to be fixed in the conftest file.
For each different method, I would like it to use different browsers for different things.
Is there any way to send arguments TO the fixture??
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import DesiredCapabilities
#pytest.fixture(scope="class", params=['chrome']) #i would like to send here dynamic fixtures.
def driver_init(request):
if request.param == 'firefox':
web_driver = webdriver.Firefox()
elif request.param == 'edge':
web_driver = webdriver.Edge() # dk:needs to be added the path
else:
options = Options()
options.add_argument(
r'user-data-dir=Users/dannyk/Library/Application Support/Google/Chrome/Default')
web_driver = webdriver.Chrome(chrome_options=options)
request.cls.driver = web_driver
yield
web_driver.close()
#pytest.mark.usefixtures("driver_init")
class BaseTest:
#pytest.fixture(autouse=True)
def init_pages(self):
self.login_page = lambda driver_type=self.driver: LoginPage(driver_type)
self.application_page = lambda driver_type=self.driver: ApplicationPage(driver_type)
class TestT4(BaseTest):
# #pytest.fixture(autouse=True)
#pytest.mark.run(order=1) #here i would like to use firefox for the driver
def test_init_firefox(self):
self.getting_start_page.go_home_page()
#pytest.mark.run(order=2) #here i would like to use chrome for the driver
def test_init_chrome(self):
self.getting_start_page.go_home_page()
You can use the "factory as fixture" pattern in conftest, which is basically an inner function inside the fixture that accepts parameters. You can then pass them from your test as arguments.
In conftest:
#pytest.fixture
def driver_init():
web_drivers = []
def _driver_init(browser):
if browser == 'firefox':
web_driver = webdriver.Firefox()
web_drivers.append(web_driver)
elif browser == 'edge':
web_driver = webdriver.Edge() # dk:needs to be added the path
web_drivers.append(web_driver)
else:
options = Options()
options.add_argument(
r'user-data-dir=Users/dannyk/Library/Application Support/Google/Chrome/Default')
web_driver = webdriver.Chrome(chrome_options=options)
web_drivers.append(web_driver)
return web_driver
yield _driver_init
for web_driver in web_drivers:
web_driver.quit()
Then, in your test:
class TestT4(BaseTest):
#pytest.mark.run(order=1) #here i would like to use firefox for the driver
def test_init_firefox(self, driver_init):
web_driver = driver_init("firefox")
#pytest.mark.run(order=2) #here i would like to use chrome for the driver
def test_init_chrome(self, driver_init):
web_driver = driver_init("chrome")
Or you can use the same concept on your def_init_pages(self): fixture to instantiate the pages and send the arguments from your tests.
Please check the official documentation here.
Update
For your first new question:
how to inject data via external commands? jenkins?
I believe what you're looking for is the def pytest_addoption(parser) fixture. It allows you to pass arguments to your test automation through the command line, when running Pytest. So you could pass the browser you want your tests to run with, locally or with Jenkins, with something like this:
In conftest:
def pytest_addoption(parser):
parser.addoption("--browser")
#pytest.fixture
def browser(request):
return request.config.getoption("--browser")
Then, on your driver_init fixture you wouldn't use the "factory as fixture" pattern:
#pytest.fixture
def driver_init(browser):
if browser == 'firefox':
web_driver = webdriver.Firefox()
elif browser == 'edge':
web_driver = webdriver.Edge() # dk:needs to be added the path
else:
options = Options()
options.add_argument(
r'user-data-dir=Users/dannyk/Library/Application Support/Google/Chrome/Default')
web_driver = webdriver.Chrome(chrome_options=options)
yield web_driver
web_driver.quit()
Then, to run your tests, you would pass the browser as argument:
pytest --browser=firefox
Please check these documents:
Pass different values to a test function, depending on command line options
pytest_addoption(parser: Parser, pluginmanager: PytestPluginManager) → None
For your second new question:
how to instanciate the two drivers here? istead of creating two same methods for each driver
I think what might be the answer is the fixture parametrization that you used on your original question, but then with the driver_init fixture I suggested earlier (you wouldn't need the def init_data(self, driver_init): fixture you wrote):
#pytest.fixture(autouse=True, params=["firefox", "chrome", "edge"])
def init_pages(self, request, driver_init):
self.login_page = LoginPage(driver_init(request.param))
self.application_page = ApplicationPage(driver_init(request.param))
Please note that I have removed the #pytest.mark.usefixtures as it has no effect when applied to another fixture. You need to declare what fixture you're using as a parameter:
#pytest.fixture(autouse=True)
def init_pages(self, init_data):
Please check the pytest.mark.usefixtures documentation
I hope this gives you more tools to figure out what you need to do to sort your problem. I'm not sure if I understand completely what you're trying to accomplish.

Test case was not running using unit test module of python [duplicate]

This question already has answers here:
What is unittest in selenium Python?
(2 answers)
Closed 2 years ago.
This test case checks the error that can occur during login functionality
from selenium import webdriver
import unittest
class LoginCheck(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
def login_error_check(self):
browser = self.driver
browser.get('https://www.saucedemo.com/')
browser.maximize_window()
usr = browser.find_element_by_id('user-name')
password = browser.find_element_by_id('password')
button = browser.find_element_by_xpath('//input[#value="LOGIN"]')
print('Hello')
usr.send_keys('standard_user')
password.send_keys('password')
button.click()
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
I am getting below message
Ran 0 tests in 0.000s
OK
repl process died unexpectedly
was expecting that it will be success but couldn't see anything. I'm learning selenium.
test ran by prefixing the 'test' to the method
from selenium import webdriver
import unittest
class LoginCheck(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome()
def test_login_error_check(self):
browser = self.driver
browser.get('https://www.saucedemo.com/')
browser.maximize_window()
usr = browser.find_element_by_id('user-name')
password = browser.find_element_by_id('password')
button = browser.find_element_by_xpath('//input[#value="LOGIN"]')
print('Hello')
usr.send_keys('standard_user')
password.send_keys('password')
button.click()
def tearDown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
This will work.

why i am not able to execute 2 nd function i.e. going_first_page

import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import HtmlTestRunner
class Environment(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome(executable_path="F:\\automation\\chromedriver.exe")
# login
def test_login(self):
driver = self.driver
driver.maximize_window()
driver.get("http://localhost/dashboatd")
self.driver.find_element_by_id('uemail').send_keys('xyz#gmail.com')
self.driver.find_element_by_id('upwd').send_keys('1234567890')
self.driver.find_element_by_id('upwd').send_keys(Keys.RETURN)
# login page
def going_first_page(self):
going_first_page = self.find_element_by_class_name('color7')
self.execute_script("arguments[0].click();", going_first_page)
new_notification = self.driver.find_element_by_class_name('fa-paper-plane')
self.driver.execute_script("arguments[0].click();", new_notification)
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main(testRunner=HtmlTestRunner.HTMLTestRunner(output='F:\\automation\\reports'))
As per python guidelines-
"A testcase is created by subclassing unittest.TestCase. The three individual tests are defined with methods whose names start with the letters test. This naming convention informs the test runner about which methods represent tests."
So, you should rename it to test_going_first_page(self) from going_first_page(self)

Python automation: How to assert if string is lower or upper case?

I'm VERY new to automation, fair warning.
I have an automation script to verify that the canonical tag of a page is present. I also need to assert that it's all lower case. Would I just create an assert after "driver.find_element..." to assert islower() ?
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import unittest
class homepage_canonical(unittest.TestCase):
def setUp(self):
global driver
driver = webdriver.Firefox()
driver.get("websiteurlhere")
def test_hpcanonical(self):
WebDriverWait(driver, 10)
driver.find_element_by_css_selector("link[href='canonicalurlhere'][rel='canonical']")
def tearDown(self):
driver.quit()
if __name__ == "__main__":
unittest.main()
I would use assertTrue :
def test_hpcanonical(self):
wait = WebDriverWait(driver, 10)
element = driver.find_element_by_css_selector("link[href='canonicalurlhere'][rel='canonical']")
self.assertTrue(element.text.islower())

Resources