Running all selenium tests inside a test case - python

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?

Related

Changing test name in python unittest using selenium

I have a question. Is it possible to change the name test in output, using python unittests?
For example, my test:
from selenium import webdriver
import unittest
from data.readData import Data
from actions.actions import Actions
from pages.notificationsPage import NotificationsPage
class NotificationsTest(unittest.TestCase):
#classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome(executable_path=Data.driver)
cls.driver.implicitly_wait(10)
cls.driver.maximize_window()
def test_order_confirmation(self):
Actions.login(self, Data.email, Data.password)
driver = self.driver
driver.get(Data.website + "Admin/Configuration/Message")
notify = NotificationsPage(driver)
notify.order_confirmation()
#classmethod
def tearDownClass(cls):
cls.driver.close()
cls.driver.quit()
if __name__ == '__main__':
unittest.main()
And my output:
I want to change the marked one test name to own string here, in this output, and also in result file in res.xml (I think it is the same value).
Is it possible?
Yes, Just simply change the name of your tests method. Just Change:
def test_order_confirmation(self):
to
def whatever_you_want_to_call_your_test(self):

How to define test methods using Python Unittest

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"

Python Selenium run multiple test classes in one selenium webdriver using with pytest

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')

Attribute error in python unittest

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.

Why pytest.mark.parametrize does not work with classes in pytest?

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

Categories

Resources