Python+Selenium自动化测试:HTML报告无日志的解决求助
问题
我是Stack Overflow、自动化测试及编程领域的新手,还请多多包涵。我已为公司完成359个自动化测试用例,且全部执行通过。在学习Selenium课程时,我了解到日志功能及通过pytest -s -v --html=report.html命令生成HTML测试报告的方法。
目前遇到的问题是:生成的report.html仅显示每个测试用例的名称,无任何日志内容。我希望能在代码中添加日志并将其显示在HTML报告中,方便非技术人员了解测试执行过程及定位失败原因。
以下是我的测试脚本片段(重复代码已封装到类中的fixture,运行正常):
import pytest import unittest import time from datetime import datetime from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.support import expected_conditions from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.common.exceptions import NoSuchElementException, TimeoutException import os from dotenv import load_dotenv load_dotenv() import random import log_config logger = log_config.set_up_logging() chromedriver_path = os.environ.get("CHROME_PATH") os.environ["PATH"] += os.pathsep + chromedriver_path from settings import CON_SELFSERVICE_URL from locators import * from baseclass import BaseClass class Test_CON_02_Coupons(unittest.TestCase, BaseClass): @pytest.fixture(autouse=True) def setup(self, request): chrome_options = Options() chrome_options.add_argument("--window-size=1920,1080") chrome_options.add_argument("--start-maximized") chrome_options.add_argument("--headless") chrome_options.add_argument("--no-sandbox") self.driver = webdriver.Chrome(options=chrome_options) self.driver.maximize_window() self.driver.implicitly_wait(60) self.vars = {} self.driver.get(CON_SELFSERVICE_URL) yield self.driver.quit() @pytest.fixture(autouse=True) def login_and_navigate(self, setup): self.driver.find_element(*username_field).click() self.driver.find_element(*username_field).send_keys(valid_username) self.driver.find_element(*password_field).click() self.driver.find_element(*password_field).send_keys(valid_password) WebDriverWait(self.driver, 30).until(EC.element_to_be_clickable(login_button)) time.sleep(0.5) self.driver.find_element(*login_button).click() time.sleep(1) alert_visible = self.driver.execute_script(""" var element = document.querySelector(arguments[0]); return element !== null && element.offsetParent !== null; """, Login_Alert[1]) if alert_visible: self.driver.find_element(*username_field).click() self.driver.find_element(*username_field).clear() self.driver.find_element(*username_field).send_keys(valid_username) self.driver.find_element(*password_field).click() self.driver.find_element(*password_field).clear() self.driver.find_element(*password_field).send_keys(valid_password) WebDriverWait(self.driver, 30).until(EC.element_to_be_clickable(login_button)) time.sleep(0.5) self.driver.find_element(*login_button).click() self.wait = WebDriverWait(self.driver, 30) WebDriverWait(self.driver, 30).until(EC.presence_of_element_located((menu_couponsv3))) self.driver.find_element(*menu_couponsv3).click() iframe = self.wait.until(EC.presence_of_element_located((coupons_iframe))) self.driver.switch_to.frame(iframe) def test_coupons_03_Search_by_Title(self): # Being able to conduct a coupon search based on a Title log = self.getLogger() self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, ".app-headline__subtitle"))) self.driver.find_element(By.XPATH, "//input[contains(@id,'mat-input-0')]").click() log.info("Click on search bar") self.driver.find_element(By.ID, "mat-input-0").send_keys("100") log.info("Input of -100-") assert "100" in self.driver.find_element(By.CSS_SELECTOR, 'td.mat-cell.cdk-cell.--long-text.--is-clickable.cdk-column-i18nFields.mat-column-i18nFields.ng-star-inserted > span').text log.info("Checking that the inputed value is in the title of the first option of the grid") self.driver.find_element(By.ID, "mat-input-0").click() log.info("Click on search bar") self.driver.find_element(By.ID, "mat-input-0").clear()
我通过baseclass.py中的getLogger方法将日志输出到logfile.log文件,内容正常,希望能将同样的日志展示在HTML报告中。baseclass.py内容如下:
import inspect import logging class BaseClass: def getLogger(self): loggerName= inspect.stack()[1][3] logger = logging.getLogger(loggerName) fileHandler = logging.FileHandler("logfile.log") formatter = logging.Formatter("%(asctime)s :%(levelname)s : %(name)s :%(message)s") fileHandler.setFormatter(formatter) logger.addHandler(fileHandler) logger.setLevel(logging.DEBUG) return logger
解决方法
要把日志集成到pytest-html生成的报告中,核心是让日志同时输出到控制台(pytest -s会捕获控制台输出并写入报告),具体修改如下:
1. 修改BaseClass中的日志配置
在getLogger方法中新增控制台处理器,让日志同时输出到文件和控制台,同时避免重复添加处理器:
import inspect import logging class BaseClass: def getLogger(self): loggerName= inspect.stack()[1][3] logger = logging.getLogger(loggerName) # 避免重复添加处理器,防止日志重复输出 if logger.hasHandlers(): return logger # 文件处理器(保留原有输出到logfile.log的功能) fileHandler = logging.FileHandler("logfile.log") file_formatter = logging.Formatter("%(asctime)s :%(levelname)s : %(name)s :%(message)s") fileHandler.setFormatter(file_formatter) # 控制台处理器(新增,用于输出到控制台供pytest-html捕获) streamHandler = logging.StreamHandler() # 可选:给控制台日志设置更简洁的格式,避免报告中信息冗余 stream_formatter = logging.Formatter("%(levelname)s : %(message)s") streamHandler.setFormatter(stream_formatter) logger.addHandler(fileHandler) logger.addHandler(streamHandler) logger.setLevel(logging.DEBUG) return logger
2. 确保测试命令参数正确
运行测试时必须保留-s参数(禁用pytest的输出捕获),这样控制台日志才能被pytest-html捕获并写入报告:
pytest -s -v --html=report.html
修改完成后,重新运行测试,生成的HTML报告中就会显示每个测试用例执行过程中的日志信息,和logfile.log中的内容对应,方便非技术人员查看测试流程和定位问题。
内容的提问来源于stack exchange,提问作者Martin M
相关产品推荐
相关产品推荐

