?
目錄
實現需求1:
檢查python package狀態——pkg_resource
hook實現自動檢測包狀態
conftest.py
hook鉤子函數
Part1:
https://blog.csdn.net/x1987200567/article/details/144915315?spm=1001.2014.3001.5501
從這里開始逐個實現Part1中的需求
實現需求1:
測試開始前檢查測試需要的python package是否安裝完成,若未安裝完成,則安裝缺失的package
檢查python package狀態——pkg_resource
python中的pkg_resource庫是用來管理python中的包的,這個庫提供了檢查python安裝包的API:
pkg_resources.require()
import pkg_resources
package = "pytest-repeat>=0.9.1"#若已安裝對應版本的包,則返回對應的包以及相關聯的包信息,否則返回exceptiontry:pkg_resources.require(package)except pkg_resources.DistributionNotFound:print(f"package not found {package}")except pkg_resources.VersionConflict:print(f"package version is wrong {package}")
?當require沒有找到相應的package時就會返回不同的exception,那么根據這些不同的exception來install 或者upgrade 對應的包。
import pkg_resources
package = "pytest-repeat>=0.9.1"#若已安裝對應版本的包,則返回對應的包以及相關聯的包信息,否則返回exceptiontry:pkg_resources.require(package)except pkg_resources.DistributionNotFound:subprocess.check_call([sys.executable, "-m", "pip", "install", package])except pkg_resources.VersionConflict:subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", package])else:print(f"{package} is already meet requirement")
上面執行Install和upgrade的操作時用到了這一行代碼
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
subprocess 是python中用于執行cmd命令的一個庫,check_call()是其中一個方法。當check_all()執行成功時返回0,失敗時返回非0。接收一個list作為參數。
def check_call(*popenargs, **kwargs):"""Run command with arguments. Wait for command to complete. Ifthe exit code was zero then return, otherwise raiseCalledProcessError. The CalledProcessError object will have thereturn code in the returncode attribute.The arguments are the same as for the call function. Example:check_call(["ls", "-l"])"""
所以實現python package檢測的完整實現代碼如下:
import subprocess
import sys
import pkg_resourcesdef check_package_status(requirements_file='requirements.txt'):"""use to check if python packages needed in test are all installed , if not , install package:param requirements_file: python package needed in the test:return:"""logger.info("checking required python package status.....")try:with open(requirements_file, 'r') as file:requirements = file.readlines()for requirement in requirements:package = requirement.strip()try:pkg_resources.require(package)except pkg_resources.DistributionNotFound:logger.info(f"{package} is not installed. Installing...")subprocess.check_call([sys.executable, "-m", "pip", "install", package])except pkg_resources.VersionConflict as e:logger.error(f"Version conflict for {package}: {e}. Updating...")subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", package])else:logger.info(f"{package} is already installed.")except Exception as e:logger.exception(f"Error while checking/installing packages: {e}")
hook實現自動檢測包狀態
上面已經實現了包檢測這個功能,那么下面的問題是如何實現每次測試開始之前都自動檢測包的狀態。pytest中提供的hook鉤子函數這個功能可以幫我們快速實現這個需求。
conftest.py
這里放一段官方的介紹,大概意思是conftest.py是一個共享test fixture的文件,所有的test fixture 都定義在conftest.py中。作用范圍可以是整個項目,也可以是文件夾內。如果作用域是整個項目,那么需要放在項目的根目錄下。
The?
conftest.py
?file serves as a means of providing fixtures for an entire directory. Fixtures defined in a?conftest.py
?can be used by any test in that package without needing to import them (pytest will automatically discover them).You can have multiple nested directories/packages containing your tests, and each directory can have its own?
conftest.py
?with its own fixtures, adding on to the ones provided by the?conftest.py
?files in parent directories.
hook鉤子函數
hook也是在conftest.py中實現的,實現方式比較簡單。pytest_sessionstart()是pytest提供的一個鉤子函數,在session被創建之后,收集和執行測試case之前被調用,所以可以執行一些測試前的配置和檢查工作。
pytest_sessionstart
(session)[source]Called after the?
Session
?object has been created and before performing collection and entering the run test loop.Parameters
session?(pytest.Session) – The pytest session object.
Return type
None
?
def check_package_status(requirements_file='requirements.txt'):pass# 測試開始時檢查當前的測試配置
@pytest.hookimpl(tryfirst=True)
def pytest_sessionstart(session):check_package_status()
這樣就完成了測試開始前對python package的自動檢測和安裝功能。完整代碼為:
import pkg_resources
import subprocess
import sys
import utils.TestLogger as testLoggerlogger = testLogger.TefLogger().get_logger()def check_package_status(requirements_file='requirements.txt'):"""use to check if python packages needed in test are all installed , if not , install package:param requirements_file: python package needed in the test:return:"""logger.info("checking required python package status.....")try:with open(requirements_file, 'r') as file:requirements = file.readlines()for requirement in requirements:package = requirement.strip()try:pkg_resources.require(package)except pkg_resources.DistributionNotFound:logger.info(f"{package} is not installed. Installing...")subprocess.check_call([sys.executable, "-m", "pip", "install", package])except pkg_resources.VersionConflict as e:logger.error(f"Version conflict for {package}: {e}. Updating...")subprocess.check_call([sys.executable, "-m", "pip", "install", "--upgrade", package])else:logger.info(f"{package} is already installed.")except Exception as e:logger.exception(f"Error while checking/installing packages: {e}")# 測試開始前檢查當前的測試配置
@pytest.hookimpl(tryfirst=True)
def pytest_sessionstart(session):check_package_status()