开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python 使用 Selenium

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_namefind_element_by_idfind_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开头。使用各种断言方法执行检查,例如assertInassertTrueassertEqual。

测试套件是测试用例、测试套件或两者的集合。它用于聚合应该一起执行的测试。测试运行器是一个组件,用于编排测试的执行并向用户提供结果。运行程序可以使用图形界面、文本界面或返回一个特殊值来指示执行测试的结果。unittestpytestnose是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教程。

未经允许不得转载:我爱分享网 » Python 使用 Selenium

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏