🐲 Chinese Docs

✅ 可靠的测试自动化

SeleniumBase

测试框架 SeleniumBase on GitHub

中文文件 <=> English Docs

Latest Release on GitHub Latest Release on PyPI SeleniumBase.io Docs SeleniumBase.io Docs SeleniumBase GitHub Actions SeleniumBase

UI自动化测试需要的一切这里都有.

🚀 立即开始 | 🧙‍♂️ 命令行选项 | 🏰 功能列表 | 👨‍🏫 学习示例 | 📱 移动测试 | 📊 测试报告
📖 API语法 | 🗺️ 创建旅游 | 🌎 语言翻译 | 🛂 MasterQA | 🤖 持续集成

Selenium 和 pytest 组合使用.

SeleniumBase

立即开始:

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
如果存在多个安装的python版本, 需要显示具体版本 (E.g. 使用 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)  # 保存当前页面的截图

chinese_test_1.py:

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.断言元素('span:contains("创建账号")')
        self.断言元素('span:contains("登录")')
        self.断言文本("新闻动态", "span#新闻动态")
        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方法将自动运行当你使用 pytestnosetests, (或包含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

接着, 在 pytestnosetests 中选择一个为您的测试启动器. (可以互换.)

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

Example Pytest Report

还可以使用--junit-xml=report。获取一个xml报告。Jenkins可以使用这个文件为您的测试显示更好的报告。

pytest test_suite.py --junit-xml=report.xml

Nosetest 报告:

--report 选项将在测试套件完成后为您提供一个漂亮的报告。

nosetests test_suite.py --report

Example Nosetest 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:

下面是为测试设置生产环境时可以做的一些事情:

下面是一个启用了附加功能的测试运行示例:

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!

如果你有任何问题,说出来! 并联系我们

如果你喜欢这个项目,请给个❤(stars)吧!

Repo Size Join the chat!

SeleniumBase on GitHub SeleniumBase on Gitter SeleniumBase on Twitter SeleniumBase on Instagram SeleniumBase on Facebook