diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..76481f5 Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index c4eaeef..4e30cb0 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ $ pip install -r requirements.txt ``` -注:安装```requirements.txt```指定依赖库的版本,这是经过测试的,有时候新的版本可会有错。 +注:安装指定依赖库的版本,这是经过测试的,有时候新的版本可会有错。 ### 配置 @@ -39,24 +39,25 @@ class RunConfig: ### 运行 -**不支持在编辑器(pycharm/ VS code ...)中运行,请在 cmd(windows)/终端(Linux)下执行。** +**可以在编辑器(pycharm/ VS code ...)中运行,推荐在 cmd(windows)/终端(Linux)下执行。** ```shell $ python run_tests.py (回归模式,生成HTML报告) $ python run_tests.py -m debug (调试模式) +$ 待补充调试模式的作用和区别 ``` ### 警告提示 -`conftest.py` 文件有一行在 pycharm 中提示错误: +`conftest.py` 文件有一行在 vscode 中提示错误: ```python from py.xml import html ``` -* 原因 +## 原因 ## -从源代码判断,py名称空间中的属性是动态创建的,这就是为什么静态分析工具pylint (pycharm)无法识别它们的原因: +从源代码判断,py名称空间中的属性是动态创建的,这就是为什么静态分析工具pylint (vscode)无法识别它们的原因: ```py apipkg.initpkg(__name__, attr={'_apipkg': apipkg}, exportdefs={ @@ -73,4 +74,8 @@ apipkg.initpkg(__name__, attr={'_apipkg': apipkg}, exportdefs={ }) ``` -所以,是pycharm 不够智能!你可以忽略这个错误。 +所以,是vscode 不够智能!你可以忽略这个错误。 + +但是,时迁尝试在vscode解决了这个问题:pip3 install py + +或许只是py库老版本没有兼容呢? diff --git a/config.py b/config.py index 63b75f6..efb32d7 100644 --- a/config.py +++ b/config.py @@ -1,15 +1,17 @@ import os PRO_PATH = os.path.dirname(os.path.abspath(__file__)) - +#配置文件or参数需要放到一个class类里的属性 class RunConfig: """ 运行测试配置 """ - # 运行测试用例的目录或文件 + # 运行测试用例的目录文件 cases_path = os.path.join(PRO_PATH, "test_dir", "test_baidu.py") + # 运行测试用例的目录文件夹下的所有测试用例 + cases_path = os.path.join(PRO_PATH, "test_dir") - # 配置浏览器驱动类型(chrome/firefox/chrome-headless/firefox-headless)。 + # 配置浏览器驱动类型(chrome/chrome-headless/grid)。 driver_type = "chrome" # 失败重跑次数 diff --git a/conftest.py b/conftest.py index bef7332..4a87f7f 100644 --- a/conftest.py +++ b/conftest.py @@ -4,21 +4,18 @@ from selenium import webdriver from selenium.webdriver import Remote from selenium.webdriver.chrome.options import Options as CH_Options -from selenium.webdriver.firefox.options import Options as FF_Options from selenium.webdriver.chrome.service import Service as ChromeService -from selenium.webdriver.firefox.service import Service as FirefoxService from webdriver_manager.chrome import ChromeDriverManager -from webdriver_manager.firefox import GeckoDriverManager from config import RunConfig # 项目目录配置 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -REPORT_DIR = BASE_DIR + "/test_report/" +REPORT_DIR = BASE_DIR + "/测试报告/" # 设置用例描述表头 def pytest_html_results_table_header(cells): - cells.insert(2, html.th('Description')) + cells.insert(2, html.th('用例描述')) cells.pop() @@ -90,11 +87,13 @@ def capture_screenshots(case_name): """ global driver file_name = case_name.split("/")[-1] - if RunConfig.NEW_REPORT is None: - raise NameError('没有初始化测试报告目录') - else: - image_dir = os.path.join(RunConfig.NEW_REPORT, "image", file_name) - RunConfig.driver.save_screenshot(image_dir) + #if RunConfig.NEW_REPORT is None: + # raise NameError('没有初始化测试报告目录!') + #else: + # image_dir = os.path.join(RunConfig.NEW_REPORT, "image", file_name) + # RunConfig.driver.save_screenshot(image_dir) + image_dir = os.path.join(RunConfig.NEW_REPORT, "image", file_name) + RunConfig.driver.save_screenshot(image_dir) # 启动浏览器 @@ -111,13 +110,8 @@ def browser(): driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install())) driver.maximize_window() - elif RunConfig.driver_type == "firefox": - # 本地firefox浏览器 - driver = webdriver.Firefox() - driver.maximize_window() - elif RunConfig.driver_type == "chrome-headless": - # chrome headless模式 + # chrome headless模式(无头模式),不打开浏览器界面,执行的UI自动化 chrome_options = CH_Options() chrome_options.add_argument("--headless") chrome_options.add_argument('--disable-gpu') @@ -126,14 +120,6 @@ def browser(): options=chrome_options, service=ChromeService(ChromeDriverManager().install())) - elif RunConfig.driver_type == "firefox-headless": - # firefox headless模式 - firefox_options = FF_Options() - firefox_options.headless = True - driver = webdriver.Firefox( - firefox_options=firefox_options, - service=FirefoxService(GeckoDriverManager().install())) - elif RunConfig.driver_type == "grid": # 通过远程节点运行 driver = Remote(command_executor='http://localhost:4444/wd/hub', @@ -159,4 +145,4 @@ def browser_close(): if __name__ == "__main__": - capture_screenshots("test_dir/test_baidu_search.test_search_python.png") + capture_screenshots("test_dir/test_baidu.py") diff --git a/run_tests.py b/run_tests.py index fc50ee4..7283a07 100644 --- a/run_tests.py +++ b/run_tests.py @@ -24,7 +24,7 @@ def init_env(new_report): 初始化测试报告目录 """ os.mkdir(new_report) - os.mkdir(new_report + "/image") + os.mkdir(new_report + "/失败截图") @click.command() @@ -35,7 +35,7 @@ def run(m): now_time = time.strftime("%Y_%m_%d_%H_%M_%S") RunConfig.NEW_REPORT = os.path.join(REPORT_DIR, now_time) init_env(RunConfig.NEW_REPORT) - html_report = os.path.join(RunConfig.NEW_REPORT, "report.html") + html_report = os.path.join(RunConfig.NEW_REPORT, "测试报告可视化网页.html") xml_report = os.path.join(RunConfig.NEW_REPORT, "junit-xml.xml") pytest.main(["-s", "-v", RunConfig.cases_path, "--html=" + html_report, diff --git a/test_init.py b/test_init.py new file mode 100644 index 0000000..8ca5b61 --- /dev/null +++ b/test_init.py @@ -0,0 +1,52 @@ +#目的:构建一个能自主更新浏览器驱动的框架(只使用谷歌浏览器) + +#导入对应的包 +from selenium import webdriver +from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys +from selenium.webdriver.common.action_chains import ActionChains +from webdriver_manager.chrome import ChromeDriverManager +from selenium.webdriver.chrome.service import Service as ChromeService +from selenium.webdriver.chrome.options import Options as CH_options +from time import sleep +from tools.SliderVerificationTool import SliderTool + +#参数实例化浏览器驱动 +#options参数设置 +chrome_options = CH_options() +chrome_options.add_experimental_option('excludeSwitches', ['enable-automation'])#去除 “Chrome正受到自动化测试软件的控制” +#chrome_options.add_argument("--headless") +#chrome_options.add_argument('--disable-gpu') +# chrome_options.add_argument("--window-size=1920x1080") +driver = webdriver.Chrome(options=chrome_options,service=ChromeService(ChromeDriverManager().install())) +#driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install())) +driver.implicitly_wait(30) + +#打开网页 +driver.get("http://pos.meituan.com/web/rms-account#/login") +#切换iframe +frame_element = driver.find_element(By.CSS_SELECTOR,"#__root_wrapper_ > div > div.introduce-bg-3TjSR > div > div.ant-col.login-section-36Fr9 > iframe") +driver.switch_to.frame(frame_element) +#点击账号登录 +driver.find_element(By.CSS_SELECTOR,"#app > div > div.header > a:nth-child(2)").click() +#输入账号 +driver.find_element(By.CSS_SELECTOR,"#account").send_keys(17808231403) +#输入密码并回车登录 +driver.find_element(By.CSS_SELECTOR,"#password").send_keys("meituan123",Keys.ENTER) + +sleep(3) +slider = driver.find_element(By.CSS_SELECTOR,"#yodaBox") +background = driver.find_element(By.CSS_SELECTOR,"#yodaBoxWrapper > label") + +SliderTool(driver,slider,background) + +sleep(2000) + + +""" +待补充: + 1、浏览器滑块验证已支持,但存在一个接口校验,导致自动化登录 无法完成,需优化 + 优化方案: + 1、使用曾经用过的面具版selenium绕过异常检测 + 2、定制化针对该接口识别的参数处理(初步尝试失败) +""" \ No newline at end of file diff --git a/test_report/2020_07_19_23_01_06/image/test_bd_search.py_test_search.png b/test_report/2020_07_19_23_01_06/image/test_bd_search.py_test_search.png deleted file mode 100644 index 9de1641..0000000 Binary files a/test_report/2020_07_19_23_01_06/image/test_bd_search.py_test_search.png and /dev/null differ diff --git a/test_report/2020_07_19_23_01_06/junit-xml.xml b/test_report/2020_07_19_23_01_06/junit-xml.xml deleted file mode 100644 index b1a9b52..0000000 --- a/test_report/2020_07_19_23_01_06/junit-xml.xml +++ /dev/null @@ -1,172 +0,0 @@ -browser = <selenium.webdriver.chrome.webdriver.WebDriver (session="e13773595aaaca74488d45366ce33b66")> -base_url = 'https://www.baidu.com' - - def test_search(browser, base_url): - """ - 搜索 pytest 关键字 - 1. 打开百度首页 - 2. 输入关键字“pytest” - 3. 点击搜索按钮 - """ - browser.get(base_url) - browser.find_element_by_id("kw").send_keys("pytest") -> browser.find_element_by_id("susss").click() - -test_dir\test_bd_search.py:13: -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ -C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:360: in find_element_by_id - return self.find_element(by=By.ID, value=id_) -C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:978: in find_element - 'value': value})['value'] -C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:321: in execute - self.error_handler.check_response(response) -_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ - -self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x000002749E2209C8> -response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\n\\tRtlGetAppContainerNamedObjectPath [0x77687C24+228]\\n\\tRtlGetAppContainerNamedObjectPath [0x77687BF4+180]\\n"}}'} - - def check_response(self, response): - """ - Checks that a JSON response from the WebDriver does not have an error. - - :Args: - - response - The JSON response from the WebDriver server as a dictionary - object. - - :Raises: If the response contains an error message. - """ - status = response.get('status', None) - if status is None or status == ErrorCode.SUCCESS: - return - value = None - message = response.get("message", "") - screen = response.get("screen", "") - stacktrace = None - if isinstance(status, int): - value_json = response.get('value', None) - if value_json and isinstance(value_json, basestring): - import json - try: - value = json.loads(value_json) - if len(value.keys()) == 1: - value = value['value'] - status = value.get('error', None) - if status is None: - status = value["status"] - message = value["value"] - if not isinstance(message, basestring): - value = message - message = message.get('message') - else: - message = value.get('message', None) - except ValueError: - pass - - exception_class = ErrorInResponseException - if status in ErrorCode.NO_SUCH_ELEMENT: - exception_class = NoSuchElementException - elif status in ErrorCode.NO_SUCH_FRAME: - exception_class = NoSuchFrameException - elif status in ErrorCode.NO_SUCH_WINDOW: - exception_class = NoSuchWindowException - elif status in ErrorCode.STALE_ELEMENT_REFERENCE: - exception_class = StaleElementReferenceException - elif status in ErrorCode.ELEMENT_NOT_VISIBLE: - exception_class = ElementNotVisibleException - elif status in ErrorCode.INVALID_ELEMENT_STATE: - exception_class = InvalidElementStateException - elif status in ErrorCode.INVALID_SELECTOR \ - or status in ErrorCode.INVALID_XPATH_SELECTOR \ - or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER: - exception_class = InvalidSelectorException - elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE: - exception_class = ElementNotSelectableException - elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE: - exception_class = ElementNotInteractableException - elif status in ErrorCode.INVALID_COOKIE_DOMAIN: - exception_class = InvalidCookieDomainException - elif status in ErrorCode.UNABLE_TO_SET_COOKIE: - exception_class = UnableToSetCookieException - elif status in ErrorCode.TIMEOUT: - exception_class = TimeoutException - elif status in ErrorCode.SCRIPT_TIMEOUT: - exception_class = TimeoutException - elif status in ErrorCode.UNKNOWN_ERROR: - exception_class = WebDriverException - elif status in ErrorCode.UNEXPECTED_ALERT_OPEN: - exception_class = UnexpectedAlertPresentException - elif status in ErrorCode.NO_ALERT_OPEN: - exception_class = NoAlertPresentException - elif status in ErrorCode.IME_NOT_AVAILABLE: - exception_class = ImeNotAvailableException - elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED: - exception_class = ImeActivationFailedException - elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS: - exception_class = MoveTargetOutOfBoundsException - elif status in ErrorCode.JAVASCRIPT_ERROR: - exception_class = JavascriptException - elif status in ErrorCode.SESSION_NOT_CREATED: - exception_class = SessionNotCreatedException - elif status in ErrorCode.INVALID_ARGUMENT: - exception_class = InvalidArgumentException - elif status in ErrorCode.NO_SUCH_COOKIE: - exception_class = NoSuchCookieException - elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN: - exception_class = ScreenshotException - elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED: - exception_class = ElementClickInterceptedException - elif status in ErrorCode.INSECURE_CERTIFICATE: - exception_class = InsecureCertificateException - elif status in ErrorCode.INVALID_COORDINATES: - exception_class = InvalidCoordinatesException - elif status in ErrorCode.INVALID_SESSION_ID: - exception_class = InvalidSessionIdException - elif status in ErrorCode.UNKNOWN_METHOD: - exception_class = UnknownMethodException - else: - exception_class = WebDriverException - if value == '' or value is None: - value = response['value'] - if isinstance(value, basestring): - if exception_class == ErrorInResponseException: - raise exception_class(response, value) - raise exception_class(value) - if message == "" and 'message' in value: - message = value['message'] - - screen = None - if 'screen' in value: - screen = value['screen'] - - stacktrace = None - if 'stackTrace' in value and value['stackTrace']: - stacktrace = [] - try: - for frame in value['stackTrace']: - line = self._value_or_default(frame, 'lineNumber', '') - file = self._value_or_default(frame, 'fileName', '<anonymous>') - if line: - file = "%s:%s" % (file, line) - meth = self._value_or_default(frame, 'methodName', '<anonymous>') - if 'className' in frame: - meth = "%s.%s" % (frame['className'], meth) - msg = " at %s (%s)" - msg = msg % (meth, file) - stacktrace.append(msg) - except TypeError: - pass - if exception_class == ErrorInResponseException: - raise exception_class(response, message) - elif exception_class == UnexpectedAlertPresentException: - alert_text = None - if 'data' in value: - alert_text = value['data'].get('text') - elif 'alert' in value: - alert_text = value['alert'].get('text') - raise exception_class(message, screen, stacktrace, alert_text) -> raise exception_class(message, screen, stacktrace) -E selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="susss"]"} -E (Session info: chrome=84.0.4147.89) - -C:\Python37\lib\site-packages\selenium\webdriver\remote\errorhandler.py:242: NoSuchElementException \ No newline at end of file diff --git a/test_report/2020_07_19_23_01_06/report.html b/test_report/2020_07_19_23_01_06/report.html deleted file mode 100644 index c35ba89..0000000 --- a/test_report/2020_07_19_23_01_06/report.html +++ /dev/null @@ -1,491 +0,0 @@ - - - - - Test Report - - - -

report.html

-

Report generated on 19-Jul-2020 at 23:01:24 by pytest-html v2.1.1

-

Environment

- - - - - - - - - - - - - - - -
JAVA_HOMEC:\Program Files\Java\jdk1.8.0_251
Packages{"pluggy": "0.13.1", "py": "1.9.0", "pytest": "5.4.3"}
PlatformWindows-10-10.0.18362-SP0
Plugins{"allure-pytest": "2.8.16", "html": "2.1.1", "metadata": "1.10.0", "rerunfailures": "9.0"}
Python3.7.7
-

Summary

-

1 tests ran in 17.83 seconds.

- 0 passed, 0 skipped, 1 failed, 0 errors, 0 expected failures, 0 unexpected passes, 1 rerun -

Results

- - - - - - - - - - - - - - - - - - - - - - - - -
ResultTestDescriptionDuration
Failedtest_dir/test_bd_search.py::test_search - - - - -

搜索 pytest 关键字

-

1. 打开百度首页

-

2. 输入关键字“pytest”

-

3. 点击搜索按钮

-

0.83
-
screenshot
-
browser = <selenium.webdriver.chrome.webdriver.WebDriver (session="e13773595aaaca74488d45366ce33b66")>
base_url = 'https://www.baidu.com'

def test_search(browser, base_url):
"""
搜索 pytest 关键字
1. 打开百度首页
2. 输入关键字“pytest”
3. 点击搜索按钮
"""
browser.get(base_url)
browser.find_element_by_id("kw").send_keys("pytest")
> browser.find_element_by_id("susss").click()

test_dir\test_bd_search.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:360: in find_element_by_id
return self.find_element(by=By.ID, value=id_)
C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:978: in find_element
'value': value})['value']
C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:321: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x000002749E2209C8>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\n\\tRtlGetAppContainerNamedObjectPath [0x77687C24+228]\\n\\tRtlGetAppContainerNamedObjectPath [0x77687BF4+180]\\n"}}'}

def check_response(self, response):
"""
Checks that a JSON response from the WebDriver does not have an error.

:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.

:Raises: If the response contains an error message.
"""
status = response.get('status', None)
if status is None or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get('value', None)
if value_json and isinstance(value_json, basestring):
import json
try:
value = json.loads(value_json)
if len(value.keys()) == 1:
value = value['value']
status = value.get('error', None)
if status is None:
status = value["status"]
message = value["value"]
if not isinstance(message, basestring):
value = message
message = message.get('message')
else:
message = value.get('message', None)
except ValueError:
pass

exception_class = ErrorInResponseException
if status in ErrorCode.NO_SUCH_ELEMENT:
exception_class = NoSuchElementException
elif status in ErrorCode.NO_SUCH_FRAME:
exception_class = NoSuchFrameException
elif status in ErrorCode.NO_SUCH_WINDOW:
exception_class = NoSuchWindowException
elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
exception_class = StaleElementReferenceException
elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
exception_class = ElementNotVisibleException
elif status in ErrorCode.INVALID_ELEMENT_STATE:
exception_class = InvalidElementStateException
elif status in ErrorCode.INVALID_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
exception_class = InvalidSelectorException
elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
exception_class = ElementNotSelectableException
elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
exception_class = ElementNotInteractableException
elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
exception_class = InvalidCookieDomainException
elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
exception_class = UnableToSetCookieException
elif status in ErrorCode.TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.SCRIPT_TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.UNKNOWN_ERROR:
exception_class = WebDriverException
elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
exception_class = UnexpectedAlertPresentException
elif status in ErrorCode.NO_ALERT_OPEN:
exception_class = NoAlertPresentException
elif status in ErrorCode.IME_NOT_AVAILABLE:
exception_class = ImeNotAvailableException
elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
exception_class = ImeActivationFailedException
elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
exception_class = MoveTargetOutOfBoundsException
elif status in ErrorCode.JAVASCRIPT_ERROR:
exception_class = JavascriptException
elif status in ErrorCode.SESSION_NOT_CREATED:
exception_class = SessionNotCreatedException
elif status in ErrorCode.INVALID_ARGUMENT:
exception_class = InvalidArgumentException
elif status in ErrorCode.NO_SUCH_COOKIE:
exception_class = NoSuchCookieException
elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
exception_class = ScreenshotException
elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
exception_class = ElementClickInterceptedException
elif status in ErrorCode.INSECURE_CERTIFICATE:
exception_class = InsecureCertificateException
elif status in ErrorCode.INVALID_COORDINATES:
exception_class = InvalidCoordinatesException
elif status in ErrorCode.INVALID_SESSION_ID:
exception_class = InvalidSessionIdException
elif status in ErrorCode.UNKNOWN_METHOD:
exception_class = UnknownMethodException
else:
exception_class = WebDriverException
if value == '' or value is None:
value = response['value']
if isinstance(value, basestring):
if exception_class == ErrorInResponseException:
raise exception_class(response, value)
raise exception_class(value)
if message == "" and 'message' in value:
message = value['message']

screen = None
if 'screen' in value:
screen = value['screen']

stacktrace = None
if 'stackTrace' in value and value['stackTrace']:
stacktrace = []
try:
for frame in value['stackTrace']:
line = self._value_or_default(frame, 'lineNumber', '')
file = self._value_or_default(frame, 'fileName', '<anonymous>')
if line:
file = "%s:%s" % (file, line)
meth = self._value_or_default(frame, 'methodName', '<anonymous>')
if 'className' in frame:
meth = "%s.%s" % (frame['className'], meth)
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == ErrorInResponseException:
raise exception_class(response, message)
elif exception_class == UnexpectedAlertPresentException:
alert_text = None
if 'data' in value:
alert_text = value['data'].get('text')
elif 'alert' in value:
alert_text = value['alert'].get('text')
raise exception_class(message, screen, stacktrace, alert_text)
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="susss"]"}
E (Session info: chrome=84.0.4147.89)

C:\Python37\lib\site-packages\selenium\webdriver\remote\errorhandler.py:242: NoSuchElementException
Reruntest_dir/test_bd_search.py::test_search - - - - -

搜索 pytest 关键字

-

1. 打开百度首页

-

2. 输入关键字“pytest”

-

3. 点击搜索按钮

-

1.10
-
screenshot
-
browser = <selenium.webdriver.chrome.webdriver.WebDriver (session="8ab137205f23c019f6ffcc6c0ad1dc46")>
base_url = 'https://www.baidu.com'

def test_search(browser, base_url):
"""
搜索 pytest 关键字
1. 打开百度首页
2. 输入关键字“pytest”
3. 点击搜索按钮
"""
browser.get(base_url)
browser.find_element_by_id("kw").send_keys("pytest")
> browser.find_element_by_id("susss").click()

test_dir\test_bd_search.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:360: in find_element_by_id
return self.find_element(by=By.ID, value=id_)
C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:978: in find_element
'value': value})['value']
C:\Python37\lib\site-packages\selenium\webdriver\remote\webdriver.py:321: in execute
self.error_handler.check_response(response)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <selenium.webdriver.remote.errorhandler.ErrorHandler object at 0x000002749E1E7CC8>
response = {'status': 404, 'value': '{"value":{"error":"no such element","message":"no such element: Unable to locate element: {\...\n\\tRtlGetAppContainerNamedObjectPath [0x77687C24+228]\\n\\tRtlGetAppContainerNamedObjectPath [0x77687BF4+180]\\n"}}'}

def check_response(self, response):
"""
Checks that a JSON response from the WebDriver does not have an error.

:Args:
- response - The JSON response from the WebDriver server as a dictionary
object.

:Raises: If the response contains an error message.
"""
status = response.get('status', None)
if status is None or status == ErrorCode.SUCCESS:
return
value = None
message = response.get("message", "")
screen = response.get("screen", "")
stacktrace = None
if isinstance(status, int):
value_json = response.get('value', None)
if value_json and isinstance(value_json, basestring):
import json
try:
value = json.loads(value_json)
if len(value.keys()) == 1:
value = value['value']
status = value.get('error', None)
if status is None:
status = value["status"]
message = value["value"]
if not isinstance(message, basestring):
value = message
message = message.get('message')
else:
message = value.get('message', None)
except ValueError:
pass

exception_class = ErrorInResponseException
if status in ErrorCode.NO_SUCH_ELEMENT:
exception_class = NoSuchElementException
elif status in ErrorCode.NO_SUCH_FRAME:
exception_class = NoSuchFrameException
elif status in ErrorCode.NO_SUCH_WINDOW:
exception_class = NoSuchWindowException
elif status in ErrorCode.STALE_ELEMENT_REFERENCE:
exception_class = StaleElementReferenceException
elif status in ErrorCode.ELEMENT_NOT_VISIBLE:
exception_class = ElementNotVisibleException
elif status in ErrorCode.INVALID_ELEMENT_STATE:
exception_class = InvalidElementStateException
elif status in ErrorCode.INVALID_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR \
or status in ErrorCode.INVALID_XPATH_SELECTOR_RETURN_TYPER:
exception_class = InvalidSelectorException
elif status in ErrorCode.ELEMENT_IS_NOT_SELECTABLE:
exception_class = ElementNotSelectableException
elif status in ErrorCode.ELEMENT_NOT_INTERACTABLE:
exception_class = ElementNotInteractableException
elif status in ErrorCode.INVALID_COOKIE_DOMAIN:
exception_class = InvalidCookieDomainException
elif status in ErrorCode.UNABLE_TO_SET_COOKIE:
exception_class = UnableToSetCookieException
elif status in ErrorCode.TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.SCRIPT_TIMEOUT:
exception_class = TimeoutException
elif status in ErrorCode.UNKNOWN_ERROR:
exception_class = WebDriverException
elif status in ErrorCode.UNEXPECTED_ALERT_OPEN:
exception_class = UnexpectedAlertPresentException
elif status in ErrorCode.NO_ALERT_OPEN:
exception_class = NoAlertPresentException
elif status in ErrorCode.IME_NOT_AVAILABLE:
exception_class = ImeNotAvailableException
elif status in ErrorCode.IME_ENGINE_ACTIVATION_FAILED:
exception_class = ImeActivationFailedException
elif status in ErrorCode.MOVE_TARGET_OUT_OF_BOUNDS:
exception_class = MoveTargetOutOfBoundsException
elif status in ErrorCode.JAVASCRIPT_ERROR:
exception_class = JavascriptException
elif status in ErrorCode.SESSION_NOT_CREATED:
exception_class = SessionNotCreatedException
elif status in ErrorCode.INVALID_ARGUMENT:
exception_class = InvalidArgumentException
elif status in ErrorCode.NO_SUCH_COOKIE:
exception_class = NoSuchCookieException
elif status in ErrorCode.UNABLE_TO_CAPTURE_SCREEN:
exception_class = ScreenshotException
elif status in ErrorCode.ELEMENT_CLICK_INTERCEPTED:
exception_class = ElementClickInterceptedException
elif status in ErrorCode.INSECURE_CERTIFICATE:
exception_class = InsecureCertificateException
elif status in ErrorCode.INVALID_COORDINATES:
exception_class = InvalidCoordinatesException
elif status in ErrorCode.INVALID_SESSION_ID:
exception_class = InvalidSessionIdException
elif status in ErrorCode.UNKNOWN_METHOD:
exception_class = UnknownMethodException
else:
exception_class = WebDriverException
if value == '' or value is None:
value = response['value']
if isinstance(value, basestring):
if exception_class == ErrorInResponseException:
raise exception_class(response, value)
raise exception_class(value)
if message == "" and 'message' in value:
message = value['message']

screen = None
if 'screen' in value:
screen = value['screen']

stacktrace = None
if 'stackTrace' in value and value['stackTrace']:
stacktrace = []
try:
for frame in value['stackTrace']:
line = self._value_or_default(frame, 'lineNumber', '')
file = self._value_or_default(frame, 'fileName', '<anonymous>')
if line:
file = "%s:%s" % (file, line)
meth = self._value_or_default(frame, 'methodName', '<anonymous>')
if 'className' in frame:
meth = "%s.%s" % (frame['className'], meth)
msg = " at %s (%s)"
msg = msg % (meth, file)
stacktrace.append(msg)
except TypeError:
pass
if exception_class == ErrorInResponseException:
raise exception_class(response, message)
elif exception_class == UnexpectedAlertPresentException:
alert_text = None
if 'data' in value:
alert_text = value['data'].get('text')
elif 'alert' in value:
alert_text = value['alert'].get('text')
raise exception_class(message, screen, stacktrace, alert_text)
> raise exception_class(message, screen, stacktrace)
E selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":"[id="susss"]"}
E (Session info: chrome=84.0.4147.89)

C:\Python37\lib\site-packages\selenium\webdriver\remote\errorhandler.py:242: NoSuchElementException
\ No newline at end of file diff --git a/tools/SliderVerificationTool.py b/tools/SliderVerificationTool.py new file mode 100644 index 0000000..4c5bbdd --- /dev/null +++ b/tools/SliderVerificationTool.py @@ -0,0 +1,41 @@ +import sys +from time import sleep +from selenium.webdriver.common.by import By +from selenium.webdriver.common.action_chains import ActionChains + +""" +获取背景图片和滑块的位置信息:通过背景图片和滑块的位置信息,以便计算滑块需要拖动的距离。 + +计算滑块需要拖动的距离:根据滑块和背景图片的位置信息,可以计算出滑块需要拖动的距离。 + +模拟鼠标操作:使用ActionChains类来模拟鼠标的拖动操作,将滑块拖动到指定位置。 +""" + + #传入driver、滑块元素、背景元素 +def SliderTool(driver,slider_ele,background_ele): + """ + 《滑块验证码处理工具》\n + 传入driver、滑块元素、背景元素\n + ps:请确保滑块和背景元素已经展示了再获取element,否则本方法可能失效 + """ + #计算滑块和背景的相对距离 + distance = slider_ele.size["width"] + background_ele.size["width"] + print(f"滑块+滑道的像素距离:{distance}") + #模拟鼠标操作(按住元素,滑动到指定位置,释放鼠标) + act = ActionChains(driver) + act.click_and_hold(slider_ele).perform() + #先滑动[distance - 5] 个像素 + act.move_by_offset(distance,0).perform() + #使用循环,每100毫秒滑动1个像素,最多移动10个像素 + for j in range(1,11): + act.move_by_offset(1,0).perform() + #打印划过的像素数量,sys.stdout.write() 输出一个字符串,包含一个回车符 \r,表示将输出内容定位到本行开头。sys.stdout.flush() 将输出内容刷新到控制台 + sys.stdout.write(f"\r已移动: [ {j} ]个像素点") + sys.stdout.flush() + sleep(0.1) + # 释放鼠标,完成滑动操作 + act.release().perform() + if slider_ele.is_displayed() == False: + print("\n滑块识别成功") + elif slider_ele.is_displayed() == True: + print("\n滑块识别失败") diff --git "a/\346\265\213\350\257\225\346\212\245\345\221\212/2023_07_14_18_38_35/junit-xml.xml" "b/\346\265\213\350\257\225\346\212\245\345\221\212/2023_07_14_18_38_35/junit-xml.xml" new file mode 100644 index 0000000..f65df25 --- /dev/null +++ "b/\346\265\213\350\257\225\346\212\245\345\221\212/2023_07_14_18_38_35/junit-xml.xml" @@ -0,0 +1 @@ + \ No newline at end of file diff --git "a/\346\265\213\350\257\225\346\212\245\345\221\212/2023_07_14_18_38_35/\346\265\213\350\257\225\346\212\245\345\221\212\345\217\257\350\247\206\345\214\226\347\275\221\351\241\265.html" "b/\346\265\213\350\257\225\346\212\245\345\221\212/2023_07_14_18_38_35/\346\265\213\350\257\225\346\212\245\345\221\212\345\217\257\350\247\206\345\214\226\347\275\221\351\241\265.html" new file mode 100644 index 0000000..26a4d63 --- /dev/null +++ "b/\346\265\213\350\257\225\346\212\245\345\221\212/2023_07_14_18_38_35/\346\265\213\350\257\225\346\212\245\345\221\212\345\217\257\350\247\206\345\214\226\347\275\221\351\241\265.html" @@ -0,0 +1,506 @@ + + + + + Test Report + + + +

测试报告可视化网页.html

+

Report generated on 14-Jul-2023 at 18:39:13 by pytest-html v3.1.1

+

Environment

+ + + + + + + + + + + + + + + +
Base URLhttps://www.baidu.com
Packages{"pluggy": "0.13.1", "pytest": "6.2.4"}
PlatformmacOS-13.1-x86_64-i386-64bit
Plugins{"base-url": "1.4.2", "html": "3.1.1", "metadata": "2.0.4", "rerunfailures": "9.1.1"}
Python3.9.6
+

Summary

+

2 tests ran in 37.75 seconds.

+ 2 passed, 0 skipped, 0 failed, 0 errors, 0 expected failures, 0 unexpected passes, 0 rerun +

Results

+ + + + + + + + + + + + + + + + + + + + + + + + +
ResultTest用例描述Duration
Passedtest_dir/test_baidu.py::TestSearch::test_baidu_search_case + + + + +

名称:百度搜索"pytest"

+

步骤:

+

1、打开浏览器

+

2、输入"pytest"关键字

+

3、点击搜索按钮

+

检查点:

+

* 检查页面标题是否包含关键字。

+

31.73
+
No log output captured.
Passedtest_dir/test_baidu.py::TestSearchSettings::test_baidu_search_setting + + + + +

名称:百度搜索设置

+

步骤:

+

1、打开百度浏览器

+

2、点击设置链接

+

3、在下拉框中"选择搜索"

+

4、点击"保存设置"

+

5、对弹出警告框保存

+

检查点:

+

* 检查是否弹出提示框

+

5.65
+
No log output captured.
\ No newline at end of file