用python的单元测试工具写网易微博API的测试样例

2010-05-16 22:59

虽然之前在Django项目中也不完整地用过单元测试工具, 但是今天是第一次用python的单元测试工具完整写出一个项目的测试样例, 于是小记录下~

需求: 测试网易微博API的python实现.

源代码可见: http://code.google.com/p/163microblog/source/browse/trunk/tests.py

话说对于偶这种初级民工, 写代码喜欢不需要动脑子地先搭个架子出来然后往里面填空, 不过偶连这个架子也是从python文档里面抄出来的:

import unittest

from session import T163Session as Session


class SessionTests(unittest.TestCase):

def testlogin(self):
self.session = Session(username="xiaket@163.com", password="notmypass")
self.assertEqual(self.session.screen_name, "xiaket")


if __name__ == "__main__":
unittest.main()

这个东西貌似是能够跑, 但是有个比较不爽的地方是密码必须放到测试样例里面去, 这个让偶很不爽. 于是网上搜了搜, 看到一个继承unittest.TestCase这个基类的__init__方法的办法:

import unittest

from session import T163Session as Session


class SessionTests(unittest.TestCase):

def __init__(self, testname, username=None, password=None):
super(SessionTests, self).__init__(testname)
self.username = username
self.password = password

def testlogin(self):
session = Session(username=self.username, password=self.password)
self.assertEqual(session.screen_name, "xiaket")

这样你在另外一个文件里面就能够对这个类进行测试了:

import unittest

from t163.tests import SessionTests


if __name__ == "__main__":
username = "xiaket@163.com"
password = "notmypass"
suite = unittest.TestSuite()
suite.addTest(SessionTests("testlogin", username, password))
unittest.TextTestRunner().run(suite)

架子搭好了, 剩下的就是苦力活, 往里面填测试样例了. 这个过程比较纠结比较繁复, 而且伴随着测试样例的逐渐完成, 我还fix了一群以前代码中的bug. 另外, 由于现在网易微博还比较不成熟, 我还不得不为一群server的错误擦屁股, 写了几个装饰器来修正API的行为. 例如, 有个微博的API能够给出follow某用户的用户的信息.当给出的用户的screen_name参数不正确时, 我们理应期待服务器返回错误代码. 但是服务器比较出人意料地返回了follow当前登录用户的用户的信息. 这导致所有查询都不是完全可靠的, 除非你在每次查询前确定你查询所使用的screen_name是有效的. 于是, 我写了这样一个装饰器加到已有函数的前面:

def check_screen_name(func):
"""
    This decorator would check the screen_name in the parameter of the original
    function.

    It is to be noted that the screen must be the first argument if we are
    using a positional parameter.
    """
def morewrapped(func):
def wrapped(kls, *args, **kwargs):
if 'screen_name' in kwargs:
_screen_name = kwargs['screen_name']
elif len(args):
_screen_name = args[0]
else:
_screen_name = None
if _screen_name:
# If the screen_name is set, we shall check if it is a valid
# screen_name. We do this by visiting the homepage of this
# screen_name:
_url = "/%s" % _screen_name
_message = "Specified user does not exist."
_err_dict = {
404: (UserNotFound, _message),
}
kls.request(_url, errors=_err_dict)
return func(kls, *args, **kwargs)
return wrapped
return morewrapped(func)

我们通过能否访问这个用户的主页来判断这个用户是否存在. 如果这个主页不能够被正常访问, 我们就抛出一个404, 这样就能相信followers这个API的结果了. 另外, 使用装饰器的好处在于, 哪天服务器端的程序更新了, 我们的代码不用做太大的修改就可以继续使用.

好吧, 话题扯回来, 总结下写了这么长时间的测试样例, 有啥经验: