Does Python Pytest have anything similiar to Java TestNG DataProvider where you can pass in a set of data for the tests? I created something to take the data from my excel list using openpyxl and it returns a dictionary which my test case test_invalidLoginWrongPassword will retrieve the email and password values from the dictionary and plug into the verification test methods. The code runs, but it looks very long and inefficient and it feels like I'm violating an oop policy. I'm a novice coder so I can't think of a way I can start making it better. Any suggestions? How can I make a method to handle this retrieving of values from the returned dictionary of the readexcel method and to be able to have the test method get access to these retrieve values? Thanks.

 from base.webdriverFactory import WebDriverFactory
 from pages.webpages.login.login_page import LoginPage
 from utilities.teststatus import TestStatus
 from utilities.read_excel import ReadExcel
 import unittest, pytest
 import utilities.custom_logger as cl
 import logging
 import inspect

class LoginTests(unittest.TestCase):
log = cl.customLogger(logging.DEBUG)

def classSetup(self, setUp):
    self.wdf = WebDriverFactory(self.browser, self.os)
    self.lp = LoginPage(self.driver)
    self.ts = TestStatus(self.driver)
    self.ex = ReadExcel(self.driver)

def test_invalidLoginBlank(self):
    self.log.info("++++++++++++++++++++++++++++++++++++STARTING test_invalidLoginBlank++++++++++++++++++++++++++++++++++++")
    result = self.lp.verifyBlankLogin()
    assert result == True #Verify login failed is true
    self.ts.markFinal("test_invalidLoginBlank", result, "Verify Can't Login with Blank Fields")
    self.log.info("++++++++++++++++++++++++++++++++++++ENDING test_invalidLoginBlank++++++++++++++++++++++++++++++++++++")

def test_invalidLoginWrongPassword(self):
    self.log.info("++++++++++++++++++++++++++++++++++++STARTING test_validLoginWrongPassword++++++++++++++++++++++++++++++++++++")
    testName = inspect.stack()[0][3]
    searchtermlist = ["email", "password"]
    pair = self.ex.getExcelData(testName, searchtermlist)
    emailv = ""
    passwordv = ""
    for i in pair:
        if i == "email":
            self.log.info("emailv is: "+emailv)
        elif i == "password":
            self.log.info("passwordv is: "+passwordv)
    self.lp.wrongLogin(email=emailv, password=passwordv)
    browser1 = self.wdf.browser
    result = self.lp.verifyWrongLogin(testbrowser=browser1)
    assert result == True # Verify login failed is True
    self.ts.markFinal("test_validLoginWrongPassword", result, "Verify Can't Login with Wrong Password")
    self.log.info("++++++++++++++++++++++++++++++++++++ENDING test_validLoginWrongPassword++++++++++++++++++++++++++++++++++++")

from openpyxl import load_workbook
import utilities.custom_logger as cl
import logging

class ReadExcel():
log = cl.customLogger(logging.DEBUG)

def __init__(self, driver):
    self.driver = driver

def getExcelData(self, testName, searchtermlist):
    wb = load_workbook(filename='/Users/angee/PycharmProjects/XomePython3/testdata/testdata.xlsx')


    #List sheets available
    sheets = wb.get_sheet_names()
    for i in sheets:
        if i == testName:
            sheet = i
    self.log.info("Got active sheet.")

    column_list = []
    row_list = []
    pair = {}

    #Get first row as headers
    rows1 = sheet.iter_rows(min_row=1, max_row=1)
    firstrowheaders = next(rows1)
    for c in firstrowheaders:

    #Get second row as the headers' values
    rows2 = sheet.iter_rows(min_row=2, max_row=2)
    secondrowvalues = next(rows2)
    for d in secondrowvalues:

    #Combine the two list to create a dictionary for key:value lookup
    pair = dict(zip(column_list, row_list))

    return pair

You've probably figured this out already, since you posted the question two months ago. But just in case, and for the benefit of anyone else who has the same question...

PyTest's approach to supporting the parameterized test case design pattern is using what they call "fixtures". Fixtures are also used for the same purpose as TestNG's @Before* and @After* annotations, which is setting up initial conditions and cleaning up after the test, so it's a good thing to learn.

But when you use fixtures for a parameterized test case, PyTest allows you to pass in a list of objects to a test method, and it will execute the test method once per item in the list. See the examples in the documentation here: https://docs.pytest.org/en/latest/fixture.html#parametrizing-fixtures

(Note that the PyTest docs consistently spells "parameterized" as "parametrized", one other thing to keep in mind as you make the transition from TestNG to PyTest)

| improve this answer | |
  • 1
    Thanks for answering my question. – seleniumappiumnewbie Aug 24 '19 at 23:13
  • You’re welcome, @seleniumappiumnewbie. If you feel it answers your question, please mark it as the accepted answer. – Todd Bradley Aug 25 '19 at 18:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.