Does pytest have something like TestNG dataprovider?



  • 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
    
    @pytest.mark.usefixtures("setUp")
    class LoginTests(unittest.TestCase):
    log = cl.customLogger(logging.DEBUG)
    
    @pytest.fixture(autouse=True)
    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)
    
    @pytest.mark.run(order=1)
    def test_invalidLoginBlank(self):
        self.log.info("++++++++++++++++++++++++++++++++++++STARTING test_invalidLoginBlank++++++++++++++++++++++++++++++++++++")
        self.lp.clickSignInLink()
        self.lp.blankLogin()
        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++++++++++++++++++++++++++++++++++++")
    
    @pytest.mark.run(order=2)
    def test_invalidLoginWrongPassword(self):
        self.log.info("++++++++++++++++++++++++++++++++++++STARTING test_validLoginWrongPassword++++++++++++++++++++++++++++++++++++")
        testName = inspect.stack()[0][3]
        self.log.info(testName)
        searchtermlist = ["email", "password"]
        pair = self.ex.getExcelData(testName, searchtermlist)
        emailv = ""
        passwordv = ""
        for i in pair:
            if i == "email":
                emailv=pair[i]
                self.log.info("emailv is: "+emailv)
            elif i == "password":
                passwordv=pair[i]
                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')
    
        sheet=wb.active
    
        #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:
            column_list.append(c.value)
    
        #Get second row as the headers' values
        rows2 = sheet.iter_rows(min_row=2, max_row=2)
        secondrowvalues = next(rows2)
        for d in secondrowvalues:
            row_list.append(d.value)
    
        #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)



Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2