网站的前端测试经常最后才做,或者指派给低级程序员去做,最多再给他们一个检查表和一个 bug 跟踪器。就可以把检查表变成一系列单元测试,用网络爬虫代替人眼进行测试。
本篇内容将介绍测试的基础知识,以及如何用 Python 网络爬虫测试各种简单或复杂的网站。
1.测试简介
什么是单元测试
对于程序员来说,测试和单元测试(unit test)这两个词基本可以看成是等价的。
单元测试通常具有以下特点:
- 每个单元测试用于测试一个组件的功能的一个方面。通常,一个组件的所有单元测试都集成在同一个类(class)里。
- 每个单元测试都可以完全独立地运行,一个单元测试需要的所有启动(setup)和卸载(teardown)都必须通过这个单元测试本身去处理。
- 每个单元测试通常至少包含一个断言(assertion)。有时,一个单元测试也许只包含一个失败状态,例如抛出异常则测试失败。
- 单元测试与生产代码是分离的。
2.Python单元测试
所有标准版 Python 安装后都有单元测试模块 unittest。只要导入并扩展 unittest.TestCase 类,就可以实现下面的功能:
- 为每个单元测试的开始和结束提供 setUp 和 tearDown 函数;
- 提供不同类型的“断言”语句,让测试成功或失败;
- 把所有以 test_ 开头的函数当作单元测试运行,忽略不带 test_ 的函数。
Python单元测试来测试2+2=4,代码如下:
import unittest
class TestAddition(unittest.TestCase):
def setUp(self):
print('Setting up the test')
def tearDown(self):
print('Tearing down the test')
def test_twoPlustwo(self):
total = 2+2
self.assertEqual(4, total);
if __name__ == '__main__':
unittest.main()
setUp 和 tearDown 这两个函数在每个测试开始和结束时都会运行一次,而不是在类中所有测试开始之前和结束之后各运行一次。
本篇内容单元测试代码开头都是
if __name__ == '__main__':
------unittest.main()
它可以让你用 unittest.TestCase 类在命令行直接运行你的单元测试。
Jupyter notebook 中,Jupyter 创建的 argv 参数可能会在单元测试中引起错误,且由于在测试运行之后,unittest 框架默认会退出 Python(这会导致notebook 内核发生错误)
所以在Jupyter notebook中,可以用以下命令启动单元测试:
if __name__ == '__main__':
------unittest.main(argv=[''], exit=False)
------%reset
第二行将所有的 argv 变量(命令行参数)设置成一个空字符串,它就会被 unnittest.main 忽略。它还阻止了 unittest 在测试运行之后退出。%reset 行也非常有用,因为它重置了内存,并销毁了所有用户在 Jupyter notebook 中创
建的变量。
测试维基百科
将 Python 的 unittest 库与网络爬虫组合起来(测试页面标题和页面某元素)
from urllib.request import urlopen
from bs4 import BeautifulSoup
import unittest
class TestWikipedia(unittest.TestCase):
bs = None
def setUpClass():
url = 'http://en.wikipedia.org/wiki/Monty_Python'
TestWikipedia.bs = BeautifulSoup(urlopen(url), 'html.parser')
def test_titleText(self):
pageTitle = TestWikipedia.bs.find('h1').get_text()
self.assertEqual('Monty Python', pageTitle);
def test_contentExists(self):
content = TestWikipedia