🐲 Chinese Docs
✅ 可靠的测试自动化
中文文件 <=> English Docs
UI自动化测试需要的一切这里都有.
🚀 立即开始 |
🧙♂️ 命令行选项 |
🏰 功能列表 |
👨🏫 学习示例 |
📱 移动测试 |
📊 测试报告
📖 API语法 |
🗺️ 创建旅游 |
🌎 语言翻译 |
🛂 MasterQA |
🤖 持续集成
立即开始:
- 需要 Python 和 Git
- 建议配合 Python virtual env . See shortcut.
- 更新 pip 以防出现警告:
python -m pip install -U pip
安装 SeleniumBase:
git clone https://github.com/seleniumbase/SeleniumBase.git
cd SeleniumBase/
pip install -r requirements.txt
python setup.py install
python3
代替 python
).
- 你也可以通过pypi安装
seleniumbase
:pip install seleniumbase
- 添加
--upgrade
或-U
来更新安装程序. - 添加
--force-reinstall
更新依赖包.
下载 webdriver:
SeleniumBase 下载 webdriver 驱动到 seleniumbase/drivers 文件夹下, 使用 install
命令:
seleniumbase install chromedriver
- 你可能需要不同的 webdriver 来对应各种网页浏览器来完成自动化测试,例如:
chromedriver
对应 Chrome,edgedriver
对应 Edge,geckodriver
对应 Firefox,operadriver
对应 Opera,iedriver
对应 Internet Explorer. - 如果你需要安装最新版本的浏览器驱动, 以以下命令获取最新版本浏览器驱动 (因兼容性原因,默认下载的版本为 chromedriver 2.44 ):
seleniumbase install chromedriver latest
使用 Chrome 运行用例:
cd examples/
pytest my_first_test.py
- 如果没指定版本则默认运行的浏览器驱动为 chromedriver, 使用指定版本的命令为:
--browser=BROWSER
. - Linux 中
--headless
为默认值 (无界面运行).你也可以在任何系统中运行无界面模式. 如果你的 Linux服务器有 GUI 界面,你也需要在界面中查看浏览器运行用例的过程,你可以添加--headed
或--gui
.
运行 my_first_test.py Demo Mode:
pytest my_first_test.py --demo
此处为相关代码 my_first_test.py:
from seleniumbase import BaseCase
BaseCase.main(__name__, __file__)
class MyTestClass(BaseCase):
def test_swag_labs(self):
self.open("https://www.saucedemo.com")
self.type("#user-name", "standard_user")
self.type("#password", "secret_sauce\n")
self.assert_element("div.inventory_list")
self.assert_exact_text("Products", "span.title")
self.click('button[name*="backpack"]')
self.click("#shopping_cart_container a")
self.assert_exact_text("Your Cart", "span.title")
self.assert_text("Backpack", "div.cart_item")
self.click("button#checkout")
self.type("#first-name", "SeleniumBase")
self.type("#last-name", "Automation")
self.type("#postal-code", "77123")
self.click("input#continue")
self.assert_text("Checkout: Overview")
self.assert_text("Backpack", "div.cart_item")
self.assert_text("29.99", "div.inventory_item_price")
self.click("button#finish")
self.assert_exact_text("Thank you for your order!", "h2")
self.assert_element('img[alt="Pony Express"]')
self.js_click("a#logout_sidebar_link")
self.assert_element("div#login_button_container")
- 默认情况下, CSS Selectors 用来查找页面元素.
- 如果你是CSS Selectors新手, 可以通过 Flukeout 游戏来帮助学习掌握.
- 在上述代码中可以看到以下相关的
SeleniumBase
方法:
from seleniumbase import BaseCase
:
self.open(URL) # 打开页面
self.click(SELECTOR) # 点击页面元素
self.type(SELECTOR, TEXT) # 输入文字 (添加 "\n" 在"TEXT"的末尾来进行换行.)
self.assert_element(SELECTOR) # 断言元素是否存在并可见
self.assert_text(TEXT) # 断言文本是否存在并可见 (可以选择某个元素选择器)
self.assert_title(PAGE_TITLE) # 断言标题是否存在并可见
self.assert_no_404_errors() # 断言不存在404错误,若存在则断言失败
self.assert_no_js_errors() # 断言不存在js错误 (Chrome-ONLY)
self.execute_script(JAVASCRIPT) # 在页面中执行js脚本
self.go_back() # 返回到上一个url链接页面
self.get_text(SELECTOR) # 获取元素的文本
self.get_attribute(SELECTOR, ATTRIBUTE) # 获取某个定位元素的指定元素属性的属性值
self.is_element_visible(SELECTOR) # 判断元素是否在页面上可见
self.is_text_visible(TEXT) # 判断文本是否在页面上可见(可提供 SELECTOR)
self.hover_and_click(HOVER_SELECTOR, CLICK_SELECTOR) # 鼠标移动在指定元素上后点击另一个元素
self.select_option_by_text(DROPDOWN_SELECTOR, OPTION_TEXT) # 选择下拉框中内容
self.switch_to_frame(FRAME_NAME) # 切换 webdriver control 到页面上指定 iframe
self.switch_to_default_content() # 切换 webdriver control out 到当前的 iframe
self.switch_to_window(WINDOW_NUMBER) # 切换不同的 window/tab
self.save_screenshot(FILE_NAME) # 保存当前页面的截图
from seleniumbase.translate.chinese import 硒测试用例
硒测试用例.main(__name__, __file__)
class 我的测试类(硒测试用例):
def test_例子1(self):
self.开启("https://zh.wikipedia.org/wiki/")
self.断言标题("维基百科,自由的百科全书")
self.断言元素('a[title="Wikipedia:关于"]')
self.如果可见请单击('button[aria-label="关闭"]')
self.如果可见请单击('button[aria-label="關閉"]')
self.断言元素('span:contains("创建账号")')
self.断言元素('span:contains("登录")')
self.输入文本('input[name="search"]', "舞龍")
self.单击('button:contains("搜索")')
self.断言文本("舞龍", "#firstHeading")
self.断言元素('img[src*="Chinese_draak.jpg"]')
self.回去()
self.输入文本('input[name="search"]', "麻婆豆腐")
self.单击('button:contains("搜索")')
self.断言文本("麻婆豆腐", "#firstHeading")
self.断言元素('figure:contains("一家中餐館的麻婆豆腐")')
self.回去()
self.输入文本('input[name="search"]', "精武英雄")
self.单击('button:contains("搜索")')
self.断言元素('img[src*="Fist_of_legend.jpg"]')
self.断言文本("李连杰", 'li a[title="李连杰"]')
from seleniumbase.translate.chinese import 硒测试用例
:
self.开启(URL) # 打开页面
self.单击(SELECTOR) # 点击页面元素
self.输入文本(SELECTOR, TEXT) # 输入文字 (添加 "\n" 在"TEXT"的末尾来进行换行.)
self.断言元素(SELECTOR) # 断言元素是否存在并可见
self.断言文本(TEXT) # 断言文本是否存在并可见 (可以选择某个元素选择器)
self.断言标题(PAGE_TITLE) # 断言标题是否存在并可见
self.检查断开的链接() # 断言不存在404错误,若存在则断言失败
self.检查JS错误() # 断言不存在js错误 (Chrome-ONLY)
self.执行脚本(JAVASCRIPT) # 在页面中执行js脚本
self.回去() # 返回到上一个url链接页面
self.获取文本(SELECTOR) # 获取元素的文本
self.获取属性(SELECTOR, ATTRIBUTE) # 获取某个定位元素的指定元素属性的属性值
self.元素是否可见(SELECTOR) # 判断元素是否在页面上可见
self.文本是否显示(TEXT) # 判断文本是否在页面上可见(可提供 SELECTOR)
self.悬停并单击(HOVER_SELECTOR, CLICK_SELECTOR) # 鼠标移动在指定元素上后点击另一个元素
self.按文本选择选项(DROPDOWN_SELECTOR, OPTION_TEXT) # 选择下拉框中内容
self.切换到帧(FRAME_NAME) # 切换 webdriver control 到页面上指定 iframe
self.切换到默认内容() # 切换 webdriver control out 到当前的 iframe
self.切换到窗口(WINDOW_NUMBER) # 切换不同的 window/tab
self.保存截图(FILE_NAME) # 保存当前页面的截图
完整的 SeleniumBase methods, 可见: Method Summary
了解更多信息:
自动化 WebDriver 技能:
SeleniumBase 自动化控制 WebDriver 操作 web browsers(浏览器),在运行失败后进行截图保存. (了解更多关于定制的启动测试用例.)
简易的代码:
SeleniumBase 使用简单简约的语法, 例如:
self.type("input", "dogs\n")
上述相似的代码在 Webdriver中变现的不是特别好: (而且下面的代码不包含 SeleniumBase 的智能等待.)
from selenium.webdriver.common.by import By
element = self.driver.find_element(by=By.CSS_SELECTOR, value="input")
element.clear()
element.send_keys("dogs")
element.submit()
如你所见,在 WebDriver 中同样的事情并不如 SeleniumBase!
使用 SeleniumBase 让你的用例变得更加简单!
(你可以在你的代码中一直使用 self.driver
.)
适用 ``pytest`` 或者 ``nosetests`` 在所有的浏览器中运行你的测试用例:
(推荐使用 pytest . Chrome 是默认的浏览器.)
pytest my_first_test.py --browser=chrome
nosetests test_suite.py --browser=firefox
Python 文件中所有以 test_
开头的python方法将自动运行当你使用 pytest
或 nosetests
, (或包含Python文件的文件夹). 还可以使用以下命令更具体地说明在文件中运行什么: (注意,pytest和nosetests的语法是不同的.)
pytest [FILE_NAME].py::[CLASS_NAME]::[METHOD_NAME]
nosetests [FILE_NAME].py:[CLASS_NAME].[METHOD_NAME]
不再有不可靠的测试:
在与页面元素进行交互之前,SeleniumBase方法会自动等待页面元素完成加载(直到超时限制)。这意味着您不再需要脚本中随机的' time.sleep() '语句.
自动/手动混合模式:
SeleniumBase包括一个名为 MasterQA的解决方案, 通过让自动化执行所有浏览器操作,同时由手动测试人员处理验证,从而加快了手动测试的速度。.
丰富的特性:
获取SeleniumBase特性的完整列表, 点击这里.
详细说明书:
下面介绍如何在各种web浏览器上运行示例脚本:
首先,为您打算使用的每个浏览器安装一个webdriver:
seleniumbase install chromedriver
seleniumbase install geckodriver
seleniumbase install edgedriver
seleniumbase install iedriver
seleniumbase install operadriver
接着, 在 pytest 和 nosetests 中选择一个为您的测试启动器. (可以互换.)
cd examples/
pytest my_first_test.py --browser=chrome
nosetests my_first_test.py --browser=firefox
(如果没有指定浏览器,则默认使用Chrome.) 对于Pytest,绿色的点表示测试通过。“F”表示测试失败。
如果示例测试运行得太快,您可以在Demo模式下运行它,方法是在命令行上添加--Demo
,它会在操作之间短暂地暂停浏览器,突出显示正在操作的页面元素,并让您实时了解测试断言的内容::
pytest my_first_test.py --demo
Pytest 包括测试发现。如果您没有指定要运行的特定文件或文件夹,pytest
将根据以下匹配条件自动搜索要运行的测试的所有子目录:
Python 文件名应是开头为 test_
或者以 _test.py
结尾.
Python 方法应以 test_
开头.
Python类名可以是任何东西,因为SeleniumBase的BaseCase
类继承自unittest
的TestCase的类。
你可以看到哪些测试是由pytest
发现使用::
pytest --collect-only -q
您可以在脚本中使用以下内容来帮助您调试问题: (如果使用pdb,请确保将“-s”添加到命令行选项中,除非已经在pytest.ini中)
import time; time.sleep(5) # Makes the test wait and do nothing for 5 seconds.
import pdb; pdb.set_trace() # Enter debugging mode. n = next, c = continue, s = step.
import pytest; pytest.set_trace() # Enter debugging mode. n = next, c = continue, s = step.
要暂停抛出异常或错误的活动测试,请添加--pdb -s
:
pytest my_first_test.py --pdb -s
上面的代码将在出现故障时打开浏览器窗口。(pdb命令:'n', 'c', 's' => next, continue, step)。
下面是Pytest附带的一些有用的命令行选项:
-v # Verbose mode. Prints the full name of each test and shows more details.
-q # Quiet mode. Print fewer details in the console output when running tests.
-x # Stop running the tests after the first failure is reached.
--html=report.html # Creates a detailed pytest-html report after tests finish.
--co | --collect-only # Show what tests would get run. (Without running them)
--co -q # (Both options together!) - Do a dry run with full test names shown.
-n=NUM # Multithread the tests using that many threads. (Speed up test runs!)
-s # See print statements. (Should be on by default with pytest.ini present.)
--junit-xml=report.xml # Creates a junit-xml report after tests finish.
--pdb # If a test fails, enter Post Mortem Debug Mode. (Don't use with CI!)
--trace # Enter Debug Mode at the beginning of each test. (Don't use with CI!)
-m=MARKER # Run tests with the specified pytest marker.
SeleniumBase 为测试提供额外的Pytest命令行选项:
--browser=BROWSER # (The web browser to use. Default: "chrome".)
--chrome # (Shortcut for "--browser=chrome". On by default.)
--edge # (Shortcut for "--browser=edge".)
--firefox # (Shortcut for "--browser=firefox".)
--safari # (Shortcut for "--browser=safari".)
--settings-file=FILE # (Override default SeleniumBase settings.)
--env=ENV # (Set the test env. Access with "self.env" in tests.)
--account=STR # (Set account. Access with "self.account" in tests.)
--data=STRING # (Extra test data. Access with "self.data" in tests.)
--var1=STRING # (Extra test data. Access with "self.var1" in tests.)
--var2=STRING # (Extra test data. Access with "self.var2" in tests.)
--var3=STRING # (Extra test data. Access with "self.var3" in tests.)
--variables=DICT # (Extra test data. Access with "self.variables".)
--user-data-dir=DIR # (Set the Chrome user data directory to use.)
--protocol=PROTOCOL # (The Selenium Grid protocol: http|https.)
--server=SERVER # (The Selenium Grid server/IP used for tests.)
--port=PORT # (The Selenium Grid port used by the test server.)
--cap-file=FILE # (The web browser's desired capabilities to use.)
--cap-string=STRING # (The web browser's desired capabilities to use.)
--proxy=SERVER:PORT # (Connect to a proxy server:port as tests are running)
--proxy=USERNAME:PASSWORD@SERVER:PORT # (Use an authenticated proxy server)
--proxy-bypass-list=STRING # (";"-separated hosts to bypass, Eg "*.foo.com")
--proxy-pac-url=URL # (Connect to a proxy server using a PAC_URL.pac file.)
--proxy-pac-url=USERNAME:PASSWORD@URL # (Authenticated proxy with PAC URL.)
--proxy-driver # (If a driver download is needed, will use: --proxy=PROXY.)
--multi-proxy # (Allow multiple authenticated proxies when multi-threaded.)
--agent=STRING # (Modify the web browser's User-Agent string.)
--mobile # (Use the mobile device emulator while running tests.)
--metrics=STRING # (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
--chromium-arg="ARG=N,ARG2" # (Set Chromium args, ","-separated, no spaces.)
--firefox-arg="ARG=N,ARG2" # (Set Firefox args, comma-separated, no spaces.)
--firefox-pref=SET # (Set a Firefox preference:value set, comma-separated.)
--extension-zip=ZIP # (Load a Chrome Extension .zip|.crx, comma-separated.)
--extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
--binary-location=PATH # (Set path of the Chromium browser binary to use.)
--driver-version=VER # (Set the chromedriver or uc_driver version to use.)
--sjw # (Skip JS Waits for readyState to be "complete" or Angular to load.)
--pls=PLS # (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
--headless # (Run tests in headless mode. The default arg on Linux OS.)
--headless2 # (Use the new headless mode, which supports extensions.)
--headed # (Run tests in headed/GUI mode on Linux OS, where not default.)
--xvfb # (Run tests using the Xvfb virtual display server on Linux OS.)
--locale=LOCALE_CODE # (Set the Language Locale Code for the web browser.)
--interval=SECONDS # (The autoplay interval for presentations & tour steps)
--start-page=URL # (The starting URL for the web browser when tests begin.)
--archive-logs # (Archive existing log files instead of deleting them.)
--archive-downloads # (Archive old downloads instead of deleting them.)
--time-limit=SECONDS # (Safely fail any test that exceeds the time limit.)
--slow # (Slow down the automation. Faster than using Demo Mode.)
--demo # (Slow down and visually see test actions as they occur.)
--demo-sleep=SECONDS # (Set the wait time after Slow & Demo Mode actions.)
--highlights=NUM # (Number of highlight animations for Demo Mode actions.)
--message-duration=SECONDS # (The time length for Messenger alerts.)
--check-js # (Check for JavaScript errors after page loads.)
--ad-block # (Block some types of display ads from loading.)
--block-images # (Block images from loading during tests.)
--do-not-track # (Indicate to websites that you don't want to be tracked.)
--verify-delay=SECONDS # (The delay before MasterQA verification checks.)
--recorder # (Enables the Recorder for turning browser actions into code.)
--rec-behave # (Same as Recorder Mode, but also generates behave-gherkin.)
--rec-sleep # (If the Recorder is enabled, also records self.sleep calls.)
--rec-print # (If the Recorder is enabled, prints output after tests end.)
--disable-js # (Disable JavaScript on websites. Pages might break!)
--disable-csp # (Disable the Content Security Policy of websites.)
--disable-ws # (Disable Web Security on Chromium-based browsers.)
--enable-ws # (Enable Web Security on Chromium-based browsers.)
--enable-sync # (Enable "Chrome Sync" on websites.)
--uc | --undetected # (Use undetected-chromedriver to evade bot-detection.)
--uc-cdp-events # (Capture CDP events when running in "--undetected" mode.)
--remote-debug # (Sync to Chrome Remote Debugger chrome://inspect/#devices)
--final-debug # (Enter Debug Mode after each test ends. Don't use with CI!)
--dashboard # (Enable the SeleniumBase Dashboard. Saved at: dashboard.html)
--dash-title=STRING # (Set the title shown for the generated dashboard.)
--enable-3d-apis # (Enables WebGL and 3D APIs.)
--swiftshader # (Use Chrome's "--use-gl=swiftshader" feature.)
--incognito # (Enable Chrome's Incognito mode.)
--guest # (Enable Chrome's Guest mode.)
--dark # (Enable Chrome's Dark mode.)
--devtools # (Open Chrome's DevTools when the browser opens.)
--rs | --reuse-session # (Reuse browser session for all tests.)
--rcs | --reuse-class-session # (Reuse session for tests in class.)
--crumbs # (Delete all cookies between tests reusing a session.)
--disable-beforeunload # (Disable the "beforeunload" event on Chrome.)
--window-size=WIDTH,HEIGHT # (Set the browser's starting window size.)
--maximize # (Start tests with the browser window maximized.)
--screenshot # (Save a screenshot at the end of each test.)
--no-screenshot # (No screenshots saved unless tests directly ask it.)
--visual-baseline # (Set the visual baseline for Visual/Layout tests.)
--wire # (Use selenium-wire's webdriver for replacing selenium webdriver.)
--external-pdf # (Set Chromium "plugins.always_open_pdf_externally":True.)
--timeout-multiplier=MULTIPLIER # (Multiplies the default timeout values.)
--list-fail-page # (After each failing test, list the URL of the failure.)
(有关详细信息,请参见命令行选项的完整列表 点击这里.)
在测试失败期间,最近一次测试运行的日志和屏幕截图将被保存到latest_logs/
文件夹中。如果在命令行选项中添加——archive_logs,或者在 settings.py中将ARCHIVE_EXISTING_LOGS
设置为True
,那么这些日志将被移动到archived_logs/
。否则,将在下一次测试运行开始时清理日志文件。test_suite.py
集合包含故意失败的测试,以便您可以看到日志记录是如何工作的。
cd examples/
pytest test_suite.py --browser=chrome
pytest test_suite.py --browser=firefox
覆盖seleniumbase/config/settings.py的一个简单方法是使用自定义设置文件。下面是要添加到测试中的命令行选项: (See examples/custom_settings.py)
--settings_file=custom_settings.py
(设置包括默认超时值、双因素auth密钥、DB凭据、S3凭据和测试使用的其他重要设置.)
要将额外的数据从命令行传递给测试,添加 --data="ANY STRING"
.
现在在您的测试中,您可以使用 self.data
来访问。
测试目录定制:
用于在SeleniumBase repo之外运行测试 Pytest, 你需要一份 pytest.ini 在根目录上。用于在SeleniumBase repo之外运行测试 Nosetests, 你需要拷贝 setup.cfg 在根目录上. (子文件夹应该包括一个空白的 "init.py" 文件。)这些文件指定测试的默认配置细节。(对于运行nosetest,还可以使用--config
指定.cfg文件。示例nosetests [MY_TEST].py--config=[MY_CONFIG].cfg
')
作为一个快捷方式,您可以运行seleniumbase mkdir [DIRECTORY_NAME]
来创建一个新的文件夹,其中已经包含了必要的文件和一些可以运行的示例测试。例子:
seleniumbase mkdir ui_tests
cd ui_tests/
pytest my_first_test.py
日志记录/失败测试的结果:
让我们尝试一个失败的测试示例:
""" test_fail.py """
from seleniumbase import BaseCase
class MyTestClass(BaseCase):
def test_find_army_of_robots_on_xkcd_desert_island(self):
self.open("https://xkcd.com/731/")
self.assert_element("div#ARMY_OF_ROBOTS", timeout=1) # This should fail
你可以运行在example
文件夹运行:
pytest test_fail.py
您会注意到,创建了一个名为“latest_logs”的日志文件夹来保存有关失败测试的信息和屏幕截图。在测试运行期间,如果您在 settings.py中将ARCHIVE_EXISTING_LOGS设置为True, 或者如果您使用--archive-logs
运行测试,那么过去的结果就会移动到archived_logs文件夹中。如果您选择不归档现有的日志,它们将被删除,并被最新测试运行的日志所取代。
创建可视化测试套件报告:
(注意:Pytest和nosetest的一些命令行参数是不同的)
Pytest 报告:
使用 --html=report.html
在您的测试套件完成后,为您提供指定名称的漂亮报告。
pytest test_suite.py --html=report.html
还可以使用--junit-xml=report
。获取一个xml报告。Jenkins可以使用这个文件为您的测试显示更好的报告。
pytest test_suite.py --junit-xml=report.xml
Nosetest 报告:
--report
选项将在测试套件完成后为您提供一个漂亮的报告。
nosetests test_suite.py --report
(注意:您可以添加--show-report
来在测试套件完成后立即显示Nosetest报告。只在本地运行测试时使用--show-report
,因为它会暂停测试运行.)
使用代理服务器:
如果您希望为您的浏览器测试使用代理服务器(仅适用于Chrome和Firefox),您可以在命令行上添加--proxy=IP_ADDRESS:PORT
作为参数。
pytest proxy_test.py --proxy=IP_ADDRESS:PORT
如果您希望使用的代理服务器需要身份验证,您可以执行以下操作 (Chrome only):
pytest proxy_test.py --proxy=USERNAME:PASSWORD@IP_ADDRESS:PORT
为了使事情更简单,您可以将您经常使用的代理添加到PROXY_LIST中 proxy_list.py, 然后使用--proxy=KEY_FROM_PROXY_LIST
来使用该键的IP_ADDRESS:PORT。
pytest proxy_test.py --proxy=proxy1
变更 User-Agent:
如果您希望为您的浏览器测试更改用户代理(仅限Chrome和Firefox),您可以在命令行上添加--agent="USER agent STRING"
作为参数。
pytest user_agent_test.py --agent="Mozilla/5.0 (Nintendo 3DS; U; ; en) Version/1.7412.EU"
为网站建设导游服务:
学习更多内容 SeleniumBase Interactive Walkthroughs (在 examples/tour_examples
文件). 这对于构建一个在线体验网站的原型非常有用。
Production Environments & Integrations:
下面是为测试设置生产环境时可以做的一些事情:
-
您可以启动 Jenkins 为定期运行测试构建服务器. 这是一个真实的Jenkins的headless浏览器自动化的例子, check out the SeleniumBase Jenkins在Azure上的例子 或者 在谷歌云上的SeleniumBase Jenkins例子.
-
您可以使用 the Selenium Grid 通过在多台机器上并行执行测试来扩展测试. 要做到这一点,请查看 SeleniumBase selenium_grid folder, 这应该有你需要的一切,包括 Selenium Grid ReadMe, 这会帮助你开始.
-
如果你用 SeleniumBase MySQL 特性 保存在服务器机器上运行的测试结果,你需要安装 MySQL Workbench 帮助你从你的数据库更容易地读和写.
-
如果你用 Slack, 您可以使用 Jenkins Slack Plugin很容易地让Jenkins jobs在那里显示结果. 另一种将消息从测试发送到Slack的方法是通过 Slack's Incoming Webhooks API.
-
如果您正在使用AWS,您可以设置一个 Amazon S3 保存来自测试的日志文件和屏幕截图的帐户. 激活此功能, 修改 settings.py 连接细节见S3部分, 添加 "
--with-s3-logging
" 在运行测试时使用命令行.
下面是一个启用了附加功能的测试运行示例:
pytest [YOUR_TEST_FILE].py --with-db-reporting --with-s3-logging
详细的方法说明和实例:
导航到web页面 (使用相关commands)
self.open("https://xkcd.com/378/") # This method opens the specified page.
self.go_back() # This method navigates the browser to the previous page.
self.go_forward() # This method navigates the browser forward in history.
self.refresh_page() # This method reloads the current page.
self.get_current_url() # This method returns the current page URL.
self.get_page_source() # This method returns the current page source.
ProTip™: 您可能需要使用get_page_source()方法和Python的find()命令来解析源代码,以找到Selenium无法找到的东西。(你可能需要温习一下你的Python编程技能。)
source = self.get_page_source()
head_open_tag = source.find('<head>')
head_close_tag = source.find('</head>', head_open_tag)
everything_inside_head = source[head_open_tag+len('<head>'):head_close_tag]
点击
单击页面上的元素:
self.click("div#my_id")
ProTip™: 在大多数web浏览器中,您可以右键单击页面并选择Inspect Element
来查看创建您自己的脚本所需的CSS选择器详细信息.
输入文本
self.type(selector, text) # 用指定的值更新来自指定元素的文本。如果元素丢失或文本字段不可编辑,则引发异常。例如:
self.type("input#id_value", "2012")
您也可以使用self.add_text()或WebDriver .send_keys()命令,但是如果文本框中已经有文本,这些命令不会首先清除文本框 如果您想键入特殊的键,这也很容易。这里有一个例子:
from selenium.webdriver.common.keys import Keys
self.find_element("textarea").send_keys(Keys.SPACE + Keys.BACK_SPACE + '\n') # The backspace should cancel out the space, leaving you with the newline
从页面上的元素获取文本
text = self.get_text("header h2")
从页面上的元素获取属性值
attribute = self.get_attribute("#comic img", "title")
断言页面上某个元素在几秒钟内存在:
self.wait_for_element_present("div.my_class", timeout=10)
(注意: 您也可以使用: self.assert_element_present(ELEMENT)
)
在数秒内断言页面上元素的可见性:
self.wait_for_element_visible("a.my_class", timeout=5)
(注意: 这个的简单版本是 self.find_element(ELEMENT)
和 self.assert_element(ELEMENT)
. find_element() version 返回元素)
由于上面的行返回元素,您可以将其与.click()组合起来,如下所示:
self.find_element("a.my_class", timeout=5).click()
# But you're better off using the following statement, which does the same thing
self.click("a.my_class") # DO IT THIS WAY!
ProTip™: 可以使用点来表示类名(例如:div.class_name
),这是CSS选择器中div[class="class_name"]
的简化版本。
你也可以使用 *=
在CSS选择器中搜索任何部分值,如下所示:
self.click('a[name*="partial_name"]')
在数秒内断言页面上元素内的文本的可见性:
self.assert_text("Make it so!", "div#trek div.picard div.quotes")
self.assert_text("Tea. Earl Grey. Hot.", "div#trek div.picard div.quotes", timeout=3)
(注意: self.find_text(TEXT, ELEMENT)
和 self.wait_for_text(TEXT, ELEMENT)
干了同一件事. 为了向后字兼容性,保留了较旧的方法名,但默认超时可能不同.)
断言 anything
self.assert_true(myvar1 == something)
self.assert_equal(var1, var2)
有用的条件语句 (with creative examples in action)
is_element_visible(selector) # is an element visible on a page
if self.is_element_visible('div#warning'):
print("Red Alert: Something bad might be happening!")
is_element_present(selector) # is an element present on a page
if self.is_element_present('div#top_secret img.tracking_cookie'):
self.contact_cookie_monster() # Not a real SeleniumBase method
else:
current_url = self.get_current_url()
self.contact_the_nsa(url=current_url, message="Dark Zone Found") # Not a real SeleniumBase method
Another example:
def is_there_a_cloaked_klingon_ship_on_this_page():
if self.is_element_present("div.ships div.klingon"):
return not self.is_element_visible("div.ships div.klingon")
return False
is_text_visible(text, selector) # is text visible on a page
def get_mirror_universe_captain_picard_superbowl_ad(superbowl_year):
selector = "div.superbowl_%s div.commercials div.transcript div.picard" % superbowl_year
if self.is_text_visible("For the Love of Marketing and Earl Grey Tea!", selector):
return "Picard HubSpot Superbowl Ad 2015"
elif self.is_text_visible("Delivery Drones... Engage", selector):
return "Picard Amazon Superbowl Ad 2015"
elif self.is_text_visible("Bing it on Screen!", selector):
return "Picard Microsoft Superbowl Ad 2015"
elif self.is_text_visible("OK Glass, Make it So!", selector):
return "Picard Google Superbowl Ad 2015"
elif self.is_text_visible("Number One, I've Never Seen Anything Like It.", selector):
return "Picard Tesla Superbowl Ad 2015"
elif self.is_text_visible("""With the first link, the chain is forged.
The first speech censored, the first thought forbidden,
the first freedom denied, chains us all irrevocably.""", selector):
return "Picard Wikimedia Superbowl Ad 2015"
elif self.is_text_visible("Let us make sure history never forgets the name ... Facebook", selector):
return "Picard Facebook Superbowl Ad 2015"
else:
raise Exception("Reports of my assimilation are greatly exaggerated.")
切换 tabs
如果您的测试打开了一个新选项卡/窗口,而现在您有多个页面,该怎么办?没有问题。您需要指定当前想要使用哪个Selenium。在选项卡/窗口之间切换很容易:
self.switch_to_window(1) # This switches to the new tab (0 is the first one)
ProTip™: iFrame遵循与新窗口相同的原则—如果要对其中的某些内容采取操作,需要指定iFrame
self.switch_to_frame('ContentManagerTextBody_ifr')
# Now you can act inside the iFrame
# .... Do something cool (here)
self.switch_to_default_content() # Exit the iFrame when you're done
处理 Pop-Up 警告
如果您的测试在浏览器中弹出了一个警告,该怎么办?没有问题。你需要切换到它,要么接受它,要么拒绝它:
self.wait_for_and_accept_alert()
self.wait_for_and_dismiss_alert()
如果您不确定在尝试接受或取消警报之前是否有警报,一种处理方法是将警报处理代码包装在try/except块中。其他方法(如.text和.send_keys())也可以使用警报.
执行定制jQuery脚本:
Query是一个强大的JavaScript库,允许您在web浏览器中执行高级操作。 如果您所在的web页面已经加载了jQuery,您可以立即开始执行jQuery脚本。 您应该知道这一点,因为web页面在HTML中会包含如下内容:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
如果您想在尚未加载jQuery的页面上使用它,这是可以的。为此,首先运行以下命令:
self.activate_jquery()
许多 websites 存在限制 Content Security Policy 防止用户将jQuery和其他外部库加载到自己的网站上。如果您需要在这样的网站上使用jQuery或其他JS库,请在命令行上添加--disable_csp
。
下面是一些在脚本中使用jQuery的例子:
self.execute_script('jQuery, window.scrollTo(0, 600)') # Scrolling the page
self.execute_script("jQuery('#annoying-widget').hide()") # Hiding elements on a page
self.execute_script("jQuery('#hidden-widget').show(0)") # Showing hidden elements on a page
self.execute_script("jQuery('#annoying-button a').remove()") # Removing elements on a page
self.execute_script("jQuery('%s').mouseover()" % (mouse_over_item)) # Mouse-over elements on a page
self.execute_script("jQuery('input#the_id').val('my_text')") # Fast text input on a page
self.execute_script("jQuery('div#dropdown a.link').click()") # Click elements on a page
self.execute_script("return jQuery('div#amazing')[0].text") # Returns the css "text" of the element given
self.execute_script("return jQuery('textarea')[2].value") # Returns the css "value" of the 3rd textarea element on the page
在下面的示例中,JavaScript用于在页面上植入代码,然后Selenium可以在此之后访问该页面:
start_page = "https://xkcd.com/465/"
destination_page = "https://github.com/seleniumbase/SeleniumBase"
self.open(start_page)
referral_link = '''<a class='analytics test' href='%s'>Free-Referral Button!</a>''' % destination_page
self.execute_script('''document.body.innerHTML = \"%s\"''' % referral_link)
self.click("a.analytics") # Clicks the generated button
(由于大众需求,这个流量生成示例已经被嵌入到SeleniumBase中 self.generate_referral(start_page, end_page)
和 self.generate_traffic(start_page, end_page, loops)
方法中.)
使用延迟的断言:
假设您想在单个测试中验证web页面上的多个不同元素,但是您不希望在一次验证多个元素之前测试失败,这样您就不必重新运行测试来查找同一页面上的更多缺失元素。这就是延迟断言的用武之地。这里的例子:
from seleniumbase import BaseCase
class MyTestClass(BaseCase):
def test_delayed_asserts(self):
self.open('https://xkcd.com/993/')
self.wait_for_element('#comic')
self.delayed_assert_element('img[alt="Brand Identity"]')
self.delayed_assert_element('img[alt="Rocket Ship"]') # Will Fail
self.delayed_assert_element('#comicmap')
self.delayed_assert_text('Fake Item', '#middleContainer') # Will Fail
self.delayed_assert_text('Random', '#middleContainer')
self.delayed_assert_element('a[name="Super Fake !!!"]') # Will Fail
self.process_delayed_asserts()
delayed_assert_element()
和 delayed_assert_text()
将保存将引发的任何异常。
要将所有失败的延迟断言清除到单个异常中, 确保在测试方法的末尾调用 self.process_delayed_asserts()
. 如果测试涉及多个页面, 可以在单个页面的所有延迟断言的末尾调用 self.process_delayed_asserts()
. 这样,日志文件的屏幕截图就会显示延迟断言的生成位置。
访问原始WebDriver
如果您需要访问标准WebDriver附带的任何命令,您可以像这样直接调用它们:
self.driver.delete_all_cookies()
capabilities = self.driver.capabilities
self.driver.find_elements_by_partial_link_text("GitHub")
(通常,您会希望在可用时使用带方法的SeleniumBase版本.)
自动重试失败的测试
你可以使用 --reruns NUM
来重试失败的用例,次数为 NUM 值. 使用 --reruns-delay SECONDS
在重试之间等待那么多秒。例子:
pytest --reruns 5 --reruns-delay 1
此外,可以使用@retry_on_exception()
装饰器来特别重试失败的方法. (需要 import: from seleniumbase import decorators
) 了解更多关于SeleniumBase装饰器的信息, click here.
简讯
祝贺您开始使用SeleniumBase!