Настройка последовательности выполнения теста в conftest.py pytest, параметризованное тестирование - PullRequest
0 голосов
/ 04 августа 2020

conftest.py:

def pytest_collection_modifyitems(config, items):
    def param_part(item):
        # check for the wanted module and test class
        if item.nodeid.startswith("test_urls.py::TestSSL::"):
            # find the start of the parameter part in the nodeid
            index = item.nodeid.find('[')
            if index > 0:
                # sort by parameter name
                return item.name[item.nodeid.index('['):]

        # for all other cases, sort by node id as usual
        return item.nodeid

    # re-order the items using the param_part function as key
    items[:] = sorted(items, key=param_part)

test_urls.py:

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from allure_commons.types import AttachmentType
import pytest
import logging
import allure


driver = webdriver.Chrome(executable_path=r'C:\chromedriver.exe')


# Logger

logging.basicConfig(filename="C:/LPsLogs/test.log",
                    format='%(asctime)s: %(levelname)s: %(message)s',
                    datefmt='%m/%d/%Y %H:%M:%S')


logger = logging.getLogger()
logger.setLevel(logging.INFO)


wait = WebDriverWait(driver, 2)
driver.implicitly_wait(2)

ec = EC
goxp = driver.find_element_by_xpath
goid = driver.find_element_by_id
keys = Keys
original_window = driver.current_window_handle

# Urls
sslurl = "https://www.sslshopper.com/ssl-checker.html"

# Locators

# xpath
sslpch = "//h1"
u1chb1 = "//div[@id='checkData']/descendant::td[1]"
u1chb2 = "//div[@id='checkData']/descendant::td[3]"
u1chb3 = "//div[@id='checkData']/descendant::td[5]"
u1chb4 = "//div[@id='checkData']/descendant::td[7]"
u1chb5 = "//div[@id='checkData']/descendant::td[11]"
u1chb6 = "//div[@id='checkData']/descendant::td[15]"

# id
hostname = "hostname"
expdate = "cert_expiration_days"


@allure.severity(allure.severity_level.BLOCKER)
def test_go_ca_sslcheck():
    logger.info("Testing started")
    driver.maximize_window()
    driver.get(sslurl)
    wait.until(EC.visibility_of_element_located((By.XPATH, sslpch)))
    sslchecker = driver.find_element_by_xpath(sslpch).text
    if sslchecker == 'SSL Checker':
        assert True
    else:
        logging.error('Error - def test_go_sslcheck module', exc_info=True)
        allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
        assert False



@pytest.mark.parametrize("url", ["https://google.com",
                                 "https://expired.badssl.com"
                                 ])
class TestSSL:
    @allure.severity(allure.severity_level.CRITICAL)
    def test_url_input(self, url):
        try:
            input_hostname = goid(hostname)
            input_hostname.send_keys(url)
            input_hostname.send_keys(keys.ENTER)
            # time.sleep(2)
            print(f"{url} has been entered")
            assert True
            input_hostname.clear()
        except (Exception, NameError, AssertionError):
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            logging.error('Error - url_input module', exc_info=True)
            assert False

    @allure.severity(allure.severity_level.CRITICAL)
    def test_url_checkbox1(self, url):
        wait.until(EC.visibility_of_element_located((By.XPATH, u1chb1)))
        u1chb1ch = driver.find_element_by_xpath(u1chb1).get_attribute('class')
        if u1chb1ch == 'passed':
            print(f"{url} - test_url_checkbox1 - PASS")
            assert True
        else:
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            logging.error(f'{url} - checkbox 1 - FAILED', exc_info=True)
            assert False

    @allure.severity(allure.severity_level.CRITICAL)
    def test_url_checkbox2(self, url):
        wait.until(EC.visibility_of_element_located((By.XPATH, u1chb2)))
        u1chb2ch = driver.find_element_by_xpath(u1chb2).get_attribute('class')
        if u1chb2ch == 'passed':
            print(f"{url} - test_url_checkbox2 - PASS")
            assert True
        else:
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            logging.error(f'{url} - checkbox 2 - FAILED', exc_info=True)
            assert False

    @allure.severity(allure.severity_level.CRITICAL)
    def test_url_checkbox3(self, url):
        wait.until(EC.visibility_of_element_located((By.XPATH, u1chb3)))
        u1chb3ch = driver.find_element_by_xpath(u1chb3).get_attribute('class')
        if u1chb3ch == 'passed':
            print(f"{url} - test_url_checkbox3 - PASS")
            assert True
        else:
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            logging.error(f'{url} - checkbox 3 - FAILED', exc_info=True)
            assert False

    @allure.severity(allure.severity_level.CRITICAL)
    def test_url_checkbox4(self, url):
        wait.until(EC.visibility_of_element_located((By.XPATH, u1chb4)))
        u1chb4ch = driver.find_element_by_xpath(u1chb4).get_attribute('class')
        if u1chb4ch == 'passed':
            print(f"{url} - test_url_checkbox4 - PASS")
            assert True
        else:
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            logging.error(f'{url} - checkbox 4 - FAILED', exc_info=True)
            assert False

    @allure.severity(allure.severity_level.CRITICAL)
    def test_url_checkbox5(self, url):
        wait.until(EC.visibility_of_element_located((By.XPATH, u1chb5)))
        u1chb5ch = driver.find_element_by_xpath(u1chb5).get_attribute('class')
        if u1chb5ch == 'passed':
            print(f"{url} - test_url_checkbox5 - PASS")
            assert True
        else:
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            logging.error(f'{url} - checkbox 5 - FAILED', exc_info=True)
            assert False

    @allure.severity(allure.severity_level.CRITICAL)
    def test_url_checkbox6(self, url):
        wait.until(EC.visibility_of_element_located((By.XPATH, u1chb6)))
        u1chb6ch = driver.find_element_by_xpath(u1chb6).get_attribute('class')
        if u1chb6ch == 'passed':
            print(f"{url} - test_url_checkbox6 - PASS")
            assert True
        else:
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            logging.error(f'{url} - checkbox 6 - FAILED', exc_info=True)
            assert False

    @allure.severity(allure.severity_level.NORMAL)
    def test_url_expdate_w(self, url):
        expdatech = driver.find_element_by_id(expdate).text
        if int(expdatech) > 7:
            print(f"{url} - expdate more than 7 days - PASS")
            assert True
        else:
            allure.attach(driver.get_screenshot_as_png(), name="testLoginScreen", attachment_type=AttachmentType.PNG)
            print(expdatech)
            logging.warning(f"{url} SSL certificate will expire in less than 7 days, days left: {expdatech}", exc_info=True)
            assert False


# def test_close_browser():
    try:
        logger.info("Testing finished")
        driver.close()
        assert True
    except (Exception, NameError, AssertionError):
        logging.error('Error - close_browser module', exc_info=True)
        assert False

Результат: Тест последовательность выполнения сейчас - https://prnt.sc/ttw4or Также conftest сортирует тесты по имени (алфавиту), мне нужно удалить эту зависимость.

Целевой результат: последовательность выполнения теста требуется - test_go_ca_sslcheck ()> итерация класса с первым URL> итерация класса со следующим URL, пока они не завершатся> def test_close_browser ()

Примечание: Возможно, есть более простой способ достичь цели, опишите пожалуйста подробно, мои знания крайне ограничены. Заранее спасибо!

1 Ответ

0 голосов
/ 04 августа 2020

Если я сейчас правильно понял, вы не хотите изменять порядок сортировки по умолчанию, кроме параметризованных тестов. Вот немного более сложная адаптированная версия, которая сделает это (я попытался добавить достаточно комментариев, чтобы объяснить это):

def pytest_collection_modifyitems(config, items):
    def param_part(item):
        index = item.name.find('[')
        if index > 0:
            # revert the name and parameter parts, so tests are sorted by
            # parameter first and name second
            return (item.name[item.name.index('['):]
                    + item.name[:item.name.index('[')])
        return item.name

    class_id = "test_urls.py::TestSSL::"
    # find the first test in the class to be sorted
    start_index = next((i for (i, item) in enumerate(items)
                        if item.nodeid.startswith(class_id)), -1)
    if start_index != -1:
        # ... and the first test after the class
        # (have to start the first at start_index)
        end_index = next((i + start_index for (i, item)
                          in enumerate(items[start_index:])
                          if not item.nodeid.startswith(class_id)), -1)
        # sort only the items in the class and let the rest alone
        items[start_index:end_index] = sorted(items[start_index:end_index],
                                              key=param_part)
    # for any other tests without our class we leave the items alone

Это дает результат для pytest -vv test_urls.py:

...
test_urls.py::test_go_ca_sslcheck PASSED                                                                         [  5%]
test_urls.py::TestSSL::test_url_checkbox1[https://expired.badssl.com] PASSED                                     [ 11%]
test_urls.py::TestSSL::test_url_checkbox2[https://expired.badssl.com] PASSED                                     [ 16%]
test_urls.py::TestSSL::test_url_checkbox3[https://expired.badssl.com] PASSED                                     [ 22%]
test_urls.py::TestSSL::test_url_checkbox4[https://expired.badssl.com] PASSED                                     [ 27%]
test_urls.py::TestSSL::test_url_checkbox5[https://expired.badssl.com] PASSED                                     [ 33%]
test_urls.py::TestSSL::test_url_checkbox6[https://expired.badssl.com] PASSED                                     [ 38%]
test_urls.py::TestSSL::test_url_expdate_w[https://expired.badssl.com] PASSED                                     [ 44%]
test_urls.py::TestSSL::test_url_input[https://expired.badssl.com] PASSED                                         [ 50%]
test_urls.py::TestSSL::test_url_checkbox1[https://google.com] PASSED                                             [ 55%]
test_urls.py::TestSSL::test_url_checkbox2[https://google.com] PASSED                                             [ 61%]
test_urls.py::TestSSL::test_url_checkbox3[https://google.com] PASSED                                             [ 66%]
test_urls.py::TestSSL::test_url_checkbox4[https://google.com] PASSED                                             [ 72%]
test_urls.py::TestSSL::test_url_checkbox5[https://google.com] PASSED                                             [ 77%]
test_urls.py::TestSSL::test_url_checkbox6[https://google.com] PASSED                                             [ 83%]
test_urls.py::TestSSL::test_url_expdate_w[https://google.com] PASSED                                             [ 88%]
test_urls.py::TestSSL::test_url_input[https://google.com] PASSED                                                 [ 94%]
test_urls.py::test_close_browser PASSED                                                                          [100%]

================================================= 18 passed in 0.16s ==================================================
...