I am using sample code with unittest but I receive an error when I execute it -- 'str' object has no attribute 'get'.
I searched Google but did not get an answer.
from selenium import webdriver
import unittest
class google1search(unittest.TestCase):
driver = 'driver'
#classmethod
def setupClass(cls):
cls.driver = webdriver.Chrome(chrome_options=options)
cls.driver.implicitly_wait(10)
cls.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(cls):
cls.driver.close()
cls.driver.quit()
print("Test completed")
if __name__== "__main__":
unittest.main()
Supposed to execute 2 steps and give result pass.
In the above code :
There is no initialization of self.driver for
self.driver.get("https://google.com")
as the driver initiated is for
cls.driver = webdriver.Chrome(chrome_options=options)
please replace cls with self
I want to extend #sarthak response little bit. In the sample code methods setUpClass and tearDownClass are used. These methods are called to prepare test class and called only once before executing all test in your test class.
Which can work in your case because at the beginning of each test you're overwriting internal state of the driver object and your previous test execution shouldn't affect your next test result. In this case you need to modify your tests to use class object:
def test_search_automationstepbystep(self):
TestClass.driver.get("https://google.com")
TestClass.driver.find_element_by_name("q").send_keys("Automation Step By step")
TestClass.driver.find_element_by_name("btnk").click()
def test_search_naresh(self):
TestClass.driver.get("https://google.com")
TestClass.driver.find_element_by_name("q").send_keys("Naresh")
TestClass.driver.find_element_by_name("btnk").click()
Where TestClass is the name of your test class.
The other option is to use setUp and tearDown methods to initialize driver object before each test case:
def setUp(self):
self.driver = webdriver.Chrome(chrome_options=options)
self.driver.implicitly_wait(10)
self.driver.maximize_window()
def tearDown(self):
self.driver.close()
self.driver.quit()
print("Test completed")
Both setUp and tearDown methods accept instance of TestClass as self argument and your tests should work without any additional changes.
Note: Usually second option is preferable for unit testing, cause you don't need to make sure in every test that you overwrite driver internal state before using find_element_by_name. And in second option you can put self.driver.get("https://google.com") code into setUp method, cause it's going to be executed before each test case anyway.
Related
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
class CorrecaoEfetivaNota(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome('/Users/r13/dev/chromedriver')
def teste_login_avaliador(self):
driver = self.driver
driver.get("")
cpf = driver.find_element_by_xpath('//input[#placeholder="CPF"]')
cpf.send_keys("")
password = driver.find_element_by_xpath('//input[#placeholder="SENHA"]')
password.send_keys("")
login = driver.find_element_by_tag_name('button')
login.click()
driver.implicitly_wait(3)
def teste_buscar_mais_um(self):
driver = self.driver
buscar = driver.find_element_by_xpath("//section[1]/div/div/section[2]/div/div/div[1]/div/div[2]/button")
buscar.click()
def tearDown(self):
self.driver.close()
I'm trying to write this tests in Python, the first function is ok, but the second one inside the class is not being executed in the tests. How can I organize this?
While working with Python and unittest module with Selenium you have to consider a few facts as follows :
Indentation for class and test_method are different.
Instead of driver.close() always invoke driver.quit() within tearDown(){} method to close & destroy the WebDriver and Web Client instances gracefully.
If you are using unittest module you have to call the __main__.
Here is your own code with the required minor modifications which will execute the first method teste_login_avaliador() as well as the second method teste_buscar_mais_um() within the Class CorrecaoEfetivaNota():
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
class CorrecaoEfetivaNota(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Chrome(executable_path=r'C:\WebDrivers\chromedriver.exe')
def teste_login_avaliador(self):
driver = self.driver
driver.get("http://d3dyod5mwyu6xk.cloudfront.net/")
cpf = driver.find_element_by_xpath('//input[#placeholder="CPF"]')
cpf.send_keys("27922797885")
password = driver.find_element_by_xpath('//input[#placeholder="SENHA"]')
password.send_keys("enccejaregular")
login = driver.find_element_by_tag_name('button')
login.click()
driver.implicitly_wait(3)
def teste_buscar_mais_um(self):
driver = self.driver
buscar = driver.find_element_by_xpath("//section[1]/div/div/section[2]/div/div/div[1]/div/div[2]/button")
buscar.click()
def tearDown(self):
self.driver.quit()
if __name__ == "__main__":
unittest.main()
Note: Though both the test_methods are being called still you will face the following exception:
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//section[1]/div/div/section[2]/div/div/div[1]/div/div[2]/button"}
At the line:
buscar = driver.find_element_by_xpath("//section[1]/div/div/section[2]/div/div/div[1]/div/div[2]/button")
This exception can be solved easily following the actual Test Steps of your usecase and if required you can raise a new question/ticket.
You write that the first function is ok, which I assume must be the setUp() function you are referring to (provided that in your code you indented correctly).
As Andersson comments, your unittest methods needs to begin with "test_" not "teste_". Providing "test_" is your way of telling unittest that this method should be tested.
In your unittest you probably also want to test something such as self.assertEqual(1,1) otherwise your tests will pass no matter what.
Next time please provide us with a more thorough description of what is wrong. How did you make the call to unittest? What error is python giving you? What result did you expect? Etc. It makes solving your problem much faster.
I encourage you to make a simple test first and ensure that it runs:
import unittest
class TestingUnittest(unittest.TestCase):
def setUp(self):
print("SetUp called")
def tearDown(self):
print("tearDown called")
def test_Method(self):
print("Testing 1==1")
self.assertEqual(1,1)
Call this from your terminal:
>>>python -m unittest "name-of-test.py"
I am new in python and I started to create an automation test suite about a GUI(multiple test cases in different file). I want to execute all my test cases in one selenium webdriver, so I created a singleton webdriver class and I want to use this class all my test cases. Here is my singleton webdriver class:
from selenium import webdriver
class Webdriver(object):
"""
Singleton class based on overriding the __new__ method
"""
def __new__(cls):
"""
Override __new__ method to control the obj. creation
:return: Singleton obj.
"""
if not hasattr(cls, 'instance'):
cls.instance = super(Webdriver, cls).__new__(cls)
return cls.instance
#staticmethod
def get_driver():
"""
:return: Selenium driver
"""
dir = "C:\\Python36\\Lib\\site-packages\\selenium\\webdriver\\ie"
ie_driver_path = dir + "\\IEDriverServer.exe"
return webdriver.Ie(ie_driver_path)
and my setUp example:
from Core.Webdriver import Webdriver
class LoginExternal(unittest.TestCase):
def setUp(self):
# Create Instances
self.web = Webdriver.get_driver()
self.matcher = TemplateMatcher()
self.gif = GifCapture("C:\\wifi\\Videos\\" + self._testMethodName + ".gif")
self.gif.start()
time.sleep(3)
def test_LoginExternal(self):
# Open External Login Page
self.web.maximize_window()
Here is my problem, when I execute my test suite, my code create a new selenium instance but I want only one selenium instance to be used in all test cases.
I use pytest as a test runner with following cmd command:
pytest --pyargs --html=Report/External_04052018.html ExternalTestSuite/
I think the problem is pytest use a new proccess in every test case execution. Is there any way to prevent or use like this way?
Pytest greatest feature and advantage over traditional XUnit family test runners is that it has fixtures. I invite you to use it. In your scenario, I would get rid of extending unittest.TestCase and setUp method in favor of pytest fixture as follows:
import pytest
from Core.Webdriver import Webdriver
class TestLoginExternal:
#pytest.fixture(scope='class')
def driver(self):
print('Setup runs once before all tests in class')
driver = Webdriver.get_driver()
yield driver
driver.quit()
print('Teardown runs once after all tests in class')
def test_LoginExternal(self, driver):
# Open External Login Page
print('test_LoginExternal')
def test_LoginInternal(self, driver):
# Open External Login Page
print('test_LoginInternal')
On executing this unittest getting
AttributeError: 'BaseUnit' object has no attribute 'driver'
import unittest
import redis
from selenium import webdriver
redis = redis.Redis(host='abc', port='123')
keys = redis.keys('*')
raw_baseunit = redis.get('test:baseunit')`enter code here`
class BaseUnit(unittest.TestCase):
def setup(self):
self.driver = webdriver.PhantomJS()
def test(self):
self.driver.get("myurl")
self.driver.find_element_by_id('username').send_keys("ngeo_pur1")
self.driver.find_element_by_id('password').send_keys("anything")
self.driver.find_element_by_xpath('html/body/div[1]/div[3]/div/section/div/form/ul/li[5]/div[2]/div/input').click()
self.driver.get("url")
self.driver.find_element_by_partial_link_text("18757424").click()
self.driver.find_element_by_xpath(".//*[#id='tabs']/nav/ul/li[2]/a/i").click()
Actual = self.driver.find_element_by_xpath(".//*[#id='subcat_baseModelSection.baseModelChoice']/div/div[1]").text
keys = redis.keys('*')
raw_baseunit = redis.get('test:baseUnit')
print "Actual Base Unit=",Actual
print "Expected Base Unit=",raw_baseunit
self.assetEquals(raw_baseunit,Actual)
def teardown(self):
self.driver.quit()
if __name__ == '__main__':
unittest.main()
Tried changing the class name 'BaseUnit' as well
Try modifying the setup class's name to this. I just read the doc and the setup class is written with the U in uppercase
def setUp(self):
self.driver = webdriver.PhantomJS()
The methods you want to override in unittest.TestCase are setUp and tearDown (note the capital "U" and "D"), not setup and teardown.
Your all-lowercase setup method doesn't get called before the test methods run (if it gets called at all), so the self.driver attribute doesn't exist when then test method tries to use it.
I have multiple tests inside one test case but I am noticing that it is only running the first test
import unittest
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.support.ui import WebDriverWait
class Test(unittest.TestCase):
def setUp(self):
self.driver = webdriver.Firefox()
self.base_url = "http://www.example.com/"
def test_Google(self):
driver = self.driver
driver.implicitly_wait(10)
driver.get(self.base_url)
def fill_contact(self):
driver.find_element_by_xpath('//a[contains(.,"Contact")]').click()
driver.implicitly_wait(10)
driver.find_element_by_xpath('//input[#type="submit"][#value="Send"]').click()
# def tearDown(self):
# self.driver.quit()
if __name__ == "__main__":
unittest.main()
Whenever I run this it only runs
def test_Google(self)
and nothing after that. am I doing something wrong?
Methods must begin with 'test' to be automatically run.
Per the docs:
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. (my emphasis)
The TestLoader is responsible for loading test and returning them wrapped in a TestSuite. It uses this method to identify tests:
class TestLoader(object):
testMethodPrefix = 'test'
def getTestCaseNames(self, testCaseClass):
"""Return a sorted sequence of method names found within testCaseClass
"""
def isTestMethod(attrname, testCaseClass=testCaseClass,
prefix=self.testMethodPrefix):
return attrname.startswith(prefix) and \
hasattr(getattr(testCaseClass, attrname), '__call__')
testFnNames = filter(isTestMethod, dir(testCaseClass))
...
Thus, the attrname.startswith(prefix) checks if the method name begins with 'test'.
As an alternative to what #unubtu noted:
you can use a nose test runner and mark a method with #istest decorator:
from nose.tools import istest
class Test(unittest.TestCase):
...
#istest
def fill_contact(self):
driver.find_element_by_xpath('//a[contains(.,"Contact")]').click()
driver.implicitly_wait(10)
driver.find_element_by_xpath('//input[#type="submit"][#value="Send"]').click()
Besides, here is a pretty good overview of the unittest test discovery:
How does Python's unittest module detect test cases?
Following code does not collect any test cases (i expect 4 to be found). Why?
import pytest
import uuid
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
class TestClass:
def __init__(self):
self.browser = webdriver.Remote(
desired_capabilities=webdriver.DesiredCapabilities.FIREFOX,
command_executor='http://my-selenium:4444/wd/hub'
)
#pytest.mark.parametrize('data', [1,2,3,4])
def test_buybuttons(self, data):
self.browser.get('http://example.com/' + data)
assert '<noindex>' not in self.browser.page_source
def __del__(self):
self.browser.quit()
If i remove __init__ and __del__ methods, it will collect tests correctly. But how i can setup and tear test down? :/
pytest won't collect test classes with an __init__ method, a more detailed explanation of why is that can be found here: py.test skips test class if constructor is defined.
You should use fixtures to define setup and tear down operations, as they are more powerful and flexible.
If you have existing tests that already have setup/tear-down methods and want to convert them to pytest, this is one straightforward approach:
class TestClass:
#pytest.yield_fixture(autouse=True)
def init_browser(self):
self.browser = webdriver.Remote(
desired_capabilities=webdriver.DesiredCapabilities.FIREFOX,
command_executor='http://my-selenium:4444/wd/hub'
)
yield # everything after 'yield' is executed on tear-down
self.browser.quit()
#pytest.mark.parametrize('data', [1,2,3,4])
def test_buybuttons(self, data):
self.browser.get('http://example.com/' + data)
assert '<noindex>' not in self.browser.page_source
More details can be found here: autouse fixtures and accessing other fixtures