Python 网页抓取 - 使用抓取器进行测试


本章介绍如何在 Python 中使用网络抓取工具执行测试。

介绍

在大型网络项目中,会定期执行网站后端的自动化测试,但经常会跳过前端测试。其背后的主要原因是网站的编程就像各种标记和编程语言的网络。我们可以为一种语言编写单元测试,但如果用另一种语言进行交互,这就变得具有挑战性。这就是为什么我们必须有一套测试来确保我们的代码按照我们的预期执行。

使用Python进行测试

当我们谈论测试时,它意味着单元测试。在深入使用 Python 进行测试之前,我们必须了解单元测试。以下是单元测试的一些特征 -

  • 在每个单元测试中至少会测试组件功能的一个方面。

  • 每个单元测试都是独立的,也可以独立运行。

  • 单元测试不会干扰任何其他测试的成功或失败。

  • 单元测试可以按任何顺序运行,并且必须至少包含一个断言。

单元测试 - Python 模块

用于单元测试的名为 Unittest 的 Python 模块随所有标准 Python 安装一起提供。我们只需要导入它,剩下的就是 unittest.TestCase 类的任务,它将执行以下操作 -

  • SetUp 和tearDown 函数由unittest.TestCase 类提供。这些函数可以在每个单元测试之前和之后运行。

  • 它还提供断言语句来允许测试通过或失败。

  • 它运行以 test_ 开头的所有函数作为单元测试。

例子

在此示例中,我们将把网络抓取与unittest结合起来。我们将测试搜索字符串“Python”的维基百科页面。它基本上会做两个测试,第一个测试标题页面是否与搜索字符串(即“Python”)相同,第二个测试确保页面有一个内容 div。

首先,我们将导入所需的 Python 模块。我们使用 BeautifulSoup 进行网页抓取,当然还使用 unittest 进行测试。

from urllib.request import urlopen
from bs4 import BeautifulSoup
import unittest

现在我们需要定义一个类来扩展unittest.TestCase。全局对象 bs 将在所有测试之间共享。单元测试指定的函数setUpClass将完成它。这里我们将定义两个函数,一个用于测试标题页,另一个用于测试页面内容。

class Test(unittest.TestCase):
   bs = None
   def setUpClass():
      url = '<a target="_blank" rel="nofollow" href="https://en.wikipedia.org/wiki/Python">https://en.wikipedia.org/wiki/Python'</a>
      Test.bs = BeautifulSoup(urlopen(url), 'html.parser')
   def test_titleText(self):
      pageTitle = Test.bs.find('h1').get_text()
      self.assertEqual('Python', pageTitle);
   def test_contentExists(self):
      content = Test.bs.find('div',{'id':'mw-content-text'})
      self.assertIsNotNone(content)
if __name__ == '__main__':
   unittest.main()

运行上述脚本后,我们将得到以下输出 -

----------------------------------------------------------------------
Ran 2 tests in 2.773s

OK
An exception has occurred, use %tb to see the full traceback.

SystemExit: False

D:\ProgramData\lib\site-packages\IPython\core\interactiveshell.py:2870:
UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
 warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)

使用Selenium进行测试

让我们讨论如何使用Python Selenium进行测试。它也称为Selenium测试。Python unittestSelenium没有太多共同点。我们知道 Selenium 会将标准 Python 命令发送到不同的浏览器,尽管浏览器的设计有所不同。回想一下,我们已经在前面的章节中安装并使用了 Selenium。在这里,我们将在 Selenium 中创建测试脚本并将其用于自动化。

例子

在下一个 Python 脚本的帮助下,我们正在为 Facebook 登录页面的自动化创建测试脚本。您可以修改示例以自动执行您选择的其他表单和登录,但概念是相同的。

首先,为了连接到网络浏览器,我们将从 selenium 模块导入 webdriver -

from selenium import webdriver

现在,我们需要从 selenium 模块导入 Keys。

from selenium.webdriver.common.keys import Keys

接下来我们需要提供用户名和密码来登录我们的 Facebook 帐户

user = "gauravleekha@gmail.com"
pwd = ""

接下来,提供 Chrome 网络驱动程序的路径。

path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path=path)
driver.get("http://www.facebook.com")

现在我们将使用assert关键字来验证条件。

assert "Facebook" in driver.title

在以下代码行的帮助下,我们将值发送到电子邮件部分。在这里,我们通过其 id 进行搜索,但我们也可以通过名称进行搜索,如driver.find_element_by_name("email")

element = driver.find_element_by_id("email")
element.send_keys(user)

在以下代码行的帮助下,我们将值发送到密码部分。这里我们通过它的 id 来搜索它,但我们也可以通过名称来搜索它,如driver.find_element_by_name("pass")

element = driver.find_element_by_id("pass")
element.send_keys(pwd)

下一行代码用于在电子邮件和密码字段中插入值后按 Enter/登录。

element.send_keys(Keys.RETURN)

现在我们将关闭浏览器。

driver.close()

运行上述脚本后,Chrome 网络浏览器将打开,您可以看到电子邮件和密码正在插入,然后单击登录按钮。

Facebook登入

比较:unittest 或 Selenium

比较unittest和selenium是很困难的,因为如果你想使用大型测试套件,则需要units的语法刚性。另一方面,如果您要测试网站的灵活性,那么 Selenium 测试将是我们的首选。但如果我们可以将它们结合起来呢?我们可以将 selenium 导入 Python unittest 并充分利用两者。Selenium 可用于获取有关网站的信息,unittest 可以评估该信息是否符合通过测试的标准。

例如,我们正在重写上面的 Python 脚本以实现 Facebook 登录的自动化,将它们结合起来,如下所示 -

import unittest
from selenium import webdriver

class InputFormsCheck(unittest.TestCase):
   def setUp(self):
      self.driver = webdriver.Chrome(r'C:\Users\gaurav\Desktop\chromedriver')
      def test_singleInputField(self):
      user = "gauravleekha@gmail.com"
      pwd = ""
      pageUrl = "http://www.facebook.com"
      driver=self.driver
      driver.maximize_window()
      driver.get(pageUrl)
      assert "Facebook" in driver.title
      elem = driver.find_element_by_id("email")
      elem.send_keys(user)
      elem = driver.find_element_by_id("pass")
      elem.send_keys(pwd)
      elem.send_keys(Keys.RETURN)
   def tearDown(self):
      self.driver.close()
if __name__ == "__main__":
   unittest.main()