PythonSelenium教程展示了如何使用Python中的Selenium框架自动化Web应用程序测试。
硒
Selenium是用于测试Web应用程序的可移植框架。Selenium可在Windows、Linux和macOS上运行。
SeleniumWebDriver是一组开源API,用于自动测试Web应用程序。有适用于Chrome、Firefox、Opera、MicrosoftEdge等浏览器的特定驱动程序。这些驱动程序需要下载并放在PATH中。SeleniumWebDriver支持不同的编程语言,包括Python、C#和Java。
Selenium可以在完整模式或无头模式下运行。在无头模式下,浏览器没有启动。
Selenium驱动程序
我们需要从https://selenium-python.readthedocs.io/installation.html#drivers下载我们使用的浏览器的驱动程序。驱动程序必须放在PATH中,例如/usr/bin/,/usr/local/bin/或当前工作目录。
PythonSelenium安装
使用以下命令安装selenium模块:
$ pip install selenium
这将安装selenium模块。
PythonSeleniumFirefox示例
对于Firefox浏览器,我们从https://github.com/mozilla/geckodriver/releases下载驱动程序(geckodriver.exeforWindows)。
#!/usr/bin/python
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
opts = Options()
opts.headless = True
driver = Firefox(options=opts)
try:
driver.get('http://webcode.me')
print(browser.title)
assert 'My html page' == driver.title
finally:
driver.quit()
在示例中,我们使用Firefox的驱动程序测试网页标题。
opts = Options() opts.headless = True driver = Firefox(options=opts)
我们以无头模式创建驱动程序。浏览器将不会启动。
try:
driver.get('http://webcode.me')
print(driver.title)
assert 'My html page' == driver.title
我们向webcode.me页面发出获取请求并获取其标题。我们对标题的内容进行断言。
finally:
driver.quit()
最后,我们退出了驱动程序。
PythonSeleniumChrome示例
对于Chrome浏览器,我们从https://sites.google.com/a/chromium.org/chromedriver/downloads下载驱动程序(chromedriver.exeforWindows)。
#!/usr/bin/python
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options
opts = Options()
opts.headless = True
driver = Chrome(options=opts, executable_path='chromedriver.exe')
try:
driver.get('http://webcode.me')
assert 'My html page!' == driver.title
finally:
driver.quit()
在这个例子中,我们使用Chrome浏览器。
driver = Chrome(options=opts, executable_path='chromedriver.exe')
我们创建了一个Chrome驱动程序的实例。executable_path指向可执行文件;如果未指定,则假定可执行文件位于PATH中。
assert 'My html page!' == driver.title
我们添加了额外的感叹号,因此测试将失败。
> py chrome_get_title.py
DevTools listening on ws://127.0.0.1:61178/devtools/browser/14d2fd68-eb2a-415a-9bf0-53a0f7b388d6
My html page
Traceback (most recent call last):
File "chrome_get_title.py", line 19, in <module>
assert 'My html page!' == driver.title
AssertionError
PythonSelenium页面源码
page_source属性获取当前页面的来源。
#!/usr/bin/python
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
opts = Options()
opts.headless = True
driver = Firefox(options=opts)
try:
driver.get('http://webcode.me')
title = driver.title
content = driver.page_source
print(content)
assert title == 'My html page'
assert 'Today is a beautiful day' in content
finally:
driver.quit()
在示例中,我们测试页面源中的标题和特定文本。
PythonSelenium查找元素
我们可以使用find_elements_by_tag_name、find_element_by_id或find_elements_by_class_name等方法来定位HTML元素并获取其内容。
#!/usr/bin/python
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
opts = Options()
opts.headless = True
driver = Firefox(options=opts)
try:
driver.get('http://webcode.me')
els = driver.find_elements_by_tag_name("p")
for el in els:
print(el.text)
finally:
driver.close()
在示例中,我们获取并打印了webcode.me首页上的两段文字。
els = driver.find_elements_by_tag_name("p")
我们使用find_elements_by_tag_name方法找到p标签。
for el in els:
print(el.text)
我们遍历元素列表并使用text属性打印它们的内容。
> py get_paragraphs.py Today is a beautiful day. We go swimming and fishing. Hello there. How are you?
PythonSelenium警告框
在下面的示例中,我们展示了如何测试JavaScript警告框。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test page</title>
</head>
<body>
<button id="mybtn" onclick="alert('Hello there!')">
Click
</button>
</body>
</html>
我们有一个带按钮的HTML页面。当我们点击按钮时,会出现一个警告框。
#!/usr/bin/python
import time
from pathlib import Path
from selenium.common.exceptions import TimeoutException
from selenium.webdriver import Firefox
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
myfile = Path.cwd() / "index.html"
driver = Firefox()
try:
driver.get(f'file://{myfile}')
button = driver.find_element_by_id("mybtn")
button.click()
time.sleep(2)
try:
WebDriverWait(driver, 3).until(ec.alert_is_present(),
'Timed out waiting for confirmation popup to appear')
alert = driver.switch_to.alert
assert alert.text == 'Hello there!'
alert.accept()
print("alert accepted")
except TimeoutException:
print("no alert")
time.sleep(5)
finally:
driver.quit()
在示例中,我们单击按钮元素并检查警告框的文本。
try:
driver.get(f'file://{myfile}')
button = driver.find_element_by_id("mybtn")
button.click()
time.sleep(2)
我们在磁盘上加载一个文件,找到按钮元素并点击它。在这个例子中,浏览器出现了;因此,我们休眠2秒,以便我们可以看到发生了什么。
WebDriverWait(driver, 3).until(ec.alert_is_present(),
'Timed out waiting for confirmation popup to appear')
使用WebDriverWait,我们等待3秒以等待警报出现。如果该框没有出现,我们会提供一条错误消息。
alert = driver.switch_to.alert assert alert.text == 'Hello there!'
我们检查警告框的文本。
PythonSelenium单元测试示例
unittest是一个Python单元测试框架。它是JUnit的Python语言版本,JUnit是Java编程语言的原始单元测试框架。unittest支持测试自动化、共享测试的设置和关闭代码、将测试聚合到集合中以及测试与报告框架的独立性。
unittest提供了一个基类,TestCase,可用于创建新的测试用例。setUp是一个钩子方法,用于在运行前设置测试夹具,tearDown是一个钩子方法,用于在测试后解构测试夹具。
testfixture表示执行一个或多个测试所需的准备工作,以及任何相关的清理操作。这可能涉及,例如,创建临时或代理数据库、目录或启动服务器进程。测试用例是指单独测试的测试函数。函数的名称必须以test开头。使用各种断言方法执行检查,例如assertIn、assertTrue或assertEqual。
测试套件是测试用例、测试套件或两者的集合。它用于聚合应该一起执行的测试。测试运行器是一个组件,用于编排测试的执行并向用户提供结果。运行程序可以使用图形界面、文本界面或返回一个特殊值来指示执行测试的结果。unittest、pytest和nose是Python测试运行器的示例。
#!/usr/bin/python
import unittest
from selenium import webdriver
from selenium.webdriver.firefox.options import Options
class WebCode(unittest.TestCase):
def setUp(self):
opts = Options()
opts.headless = True
self.driver = webdriver.Firefox(options=opts)
def test_title(self):
self.driver.get("http://webcode.me")
self.assertIn("My html page", self.driver.title)
def test_paragraphs(self):
self.driver.get("http://webcode.me")
els = self.driver.find_elements_by_tag_name("p")
self.assertIn('Today is a beautiful day', els[0].text)
self.assertIn('Hello there', els[1].text)
def tearDown(self):
self.driver.close()
if __name__ == "__main__":
unittest.main()
我们有一个测试文件,我们在其中检查webcode.me主页的标题和段落。
def setUp(self):
opts = Options()
opts.headless = True
self.driver = webdriver.Firefox(options=opts)
在setUp方法中,我们设置了Firefox驱动程序。
def test_title(self):
self.driver.get("http://webcode.me")
self.assertIn("My html page", self.driver.title)
test_title方法是单个测试用例,它使用assertIn方法检查指定网页的标题。
def test_paragraphs(self):
self.driver.get("http://webcode.me")
els = self.driver.find_elements_by_tag_name("p")
self.assertIn('Today is a beautiful day', els[0].text)
self.assertIn('Hello there', els[1].text)
在test_paragraphs测试用例中,我们检查两个段落的内容。
def tearDown(self):
self.driver.close()
在tearDown方法中,我们关闭驱动程序。
if __name__ == "__main__":
unittest.main()
使用main方法,我们执行测试。
> py unittest_example.py .. ---------------------------------------------------------------------- Ran 2 tests in 13.273s OK
我们运行测试。unittest显示一个点表示成功执行的测试用例,F表示失败的测试用例,E表示在测试执行期间发生的错误。
PythonSelenium与pytest
pytest模块是一个用于测试Python应用程序的Python库。它是nose和unittest的替代品。
$ pip install pytest
我们安装了pytest库。
pytest在目录中查找test_*.py或*_test.py文件。在选定的文件中,pytest在类之外查找带有test前缀的测试函数,并在带有Test前缀的测试类中查找带有test前缀的测试方法(没有__init__方法)).
#!/usr/bin/python
import pytest
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
@pytest.fixture
def browser():
opts = Options()
opts.headless = True
driver = Firefox(options=opts)
driver.implicitly_wait(5)
yield driver
# For cleanup, quit the driver
driver.quit()
def test_get_title(browser):
browser.get("http://webcode.me")
assert 'My html page' == browser.title
该示例显示了一个带有pytest模块的简单测试用例。
@pytest.fixture
def browser():
opts = Options()
opts.headless = True
driver = Firefox(options=opts)
...
我们定义了一个夹具。它设置Firefox驱动程序。
driver.implicitly_wait(5)
我们在尝试交互之前隐式等待元素准备就绪。
yield driver
使用yield关键字,我们在设置结束时返回驱动程序对象。
def test_get_title(browser):
browser.get("http://webcode.me")
assert 'My html page' == browser.title
我们有一个检查网页标题的测试方法。它接收浏览器装置作为参数。
> pytest ============================== test session starts ============================== platform win32 -- Python 3.8.1, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: C:\Users\Jano\Documents\python\SeleniumPytest collected 1 item tests\test_web.py . [100%] =============================== 1 passed in 6.31s ===============================
我们运行测试。
PythonSeleniumFlask示例
在下一个示例中,我们使用pytest和Selenium为Flask网络应用程序创建一个测试用例。我们测试来自HTML表单的响应。
app.py
ââââstatic
â greet.html
ââââtemplates
â index.html
ââââtests
web_test.py
这是项目结构。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Greet form</title>
</head>
<body>
<p>Enter your name:</p>
<form id="myform" action="greet">
<input name="name" type="text">
<button type="submit">Submit</button>
</form>
</body>
</html>
我们在静态资源中有一个greet表单。表单向Flask应用程序发送一个文本值。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Greeting</title>
</head>
<body>
<p>
Hello {{ name }}
</p>
</body>
</html>
这是Flask模板文件,它向客户端返回一条消息。
#!/usr/bin/python
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/")
def home():
return app.send_static_file('greet.html')
@app.route("/greet")
def greet():
username = request.args.get('name')
return render_template('index.html', name=username)
if __name__ == "__main__":
app.run()
Flask应用有两种路由:一种用于主页,一种用于问候语。
#!/usr/bin/python
import pytest
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
@pytest.fixture
def browser():
opts = Options()
opts.headless = True
driver = Firefox(options=opts)
driver.implicitly_wait(10)
yield driver
# For cleanup, quit the driver
driver.quit()
def test_greet_form(browser):
user_name = "John"
browser.get('http://localhost:5000/')
form = browser.find_element_by_id("myform")
name = browser.find_element_by_name("name")
name.send_keys(user_name)
form.submit()
WebDriverWait(browser, 12).until(ec.url_matches('/greet'),
'Timed out waiting for response')
content = browser.page_source
print(content)
assert 'Hello John' in content
web_test.py包含问候语表单的测试用例。
def test_greet_form(browser):
user_name = "John"
browser.get('http://localhost:5000/')
...
首先,我们得到问候语形式。
form = browser.find_element_by_id("myform")
name = browser.find_element_by_name("name")
name.send_keys(user_name)
form.submit()
我们检索表单的元素。我们将测试用户名添加到输入标签中并提交表单。
WebDriverWait(browser, 12).until(ec.url_matches('/greet'),
'Timed out waiting for response')
我们等待Flask重定向到/greet路由。
content = browser.page_source print(content) assert 'Hello John' in content
我们收到响应并检查响应中的消息。
> set FLASK_APP=app.py > flask run
我们运行Flask应用程序。
> pytest ========================== test session starts =========================== platform win32 -- Python 3.8.1, pytest-5.3.5, py-1.8.1, pluggy-0.13.1 rootdir: C:\Users\Jano\PycharmProjects\SeleniumPytestFlask collected 1 item tests\web_test.py . [100%] =========================== 1 passed in 12.44s ===========================
从不同的shell,我们执行pytest。
在本教程中,我们使用了PythonSelenium框架。
列出所有Python教程。
