Blog信息 |
blog名称: 日志总数:1304 评论数量:2242 留言数量:5 访问次数:7584155 建立时间:2006年5月29日 |

| |
[TurboGears]Testing Multi-user TurboGears Applications 软件技术
lhwork 发表于 2007/2/16 12:06:49 |
Lately I’ve started to write many unit
tests for my secret turbogears project. My secret project, like many
other web 2.0 applications, can have a lot of users logged in at the
same time and the actions of one user can affect other users.
The current testing tools provided by TurboGears do not give “one
obvious way” to test multi-user scenarios. I came up last week with a
simple class that will emulate a browser session of a single user
against a cherrypy server. Its only task is actually to keep track of
the visit cookie. This is a simple example of how I use it:
def test_breaking_in(): user = BrowserSession() user.goto('/directory/for/members') assert 'You must login' in user.response assert '403' in user.status user.goto('/login?username=thesamet&password=secret') user.goto('/directory/for/members') assert 'Welcome to the members area' in user.response
The BrowserSession object truly shines when your testcase includes two users (or more):
def test_object_lock(): user1 = BrowserSession() user2 = BrowserSession() user1.goto('/login?username=user1&password=pass1') user2.goto('/login?username=user2&password=pass2') user1.goto('/edit?page=pagex') user2.goto('/edit?page=pagex') assert 'Page is locked by user1' in user2.response user1.goto('/edit?page=pagex') assert "page is locked by user1" not in user1.response
and no - my secret project is not another wiki. I later found it
very convenient to put test methods inside a TestCase object rather
than many individual test functions. One of the benefits is that you
can factor out the repeating code of the logins that appear in many
tests to the setUp() method. In each test method, we will have new and
fresh sessions:
class TwoUsersTestCase(unittest.TestCase): def setUp(self): self.user1 = BrowserSession() self.user2 = BrowserSession() self.user1.goto('/login?username=user1&password=pass1') self.user2.goto('/login?username=user2&password=pass2')class SendPrivateMessageTestCase(TwoUsersTestCase): def test_send_message(self): self.user1.goto('/chat/send?to=user2&text=hello') self.user2.goto('/chat/receive') assert 'hello' in self.user2.response def test_flood_detection(self): for x in xrange(100): self.user1.goto('/chat/send?to=user2&text=hello') self.user2.goto('/chat/receive') assert 'user1 kicked out (flooding)' in self.user2.response
Now I’ll share with you the BrowserSession code. Feel free to use it:
import cherrypyfrom turbogears import testutildef cookie_header(morsel): """Returns a dict containing cookie information to pass to a server.""" return {'Cookie': morsel.output(header="")[1:]}class BrowserSession(object): def __init__(self): self.cookie_name = turbogears.config.get('visit.cookie.name', 'tg-visit') self.visit = None self.response, self.status = None, None def goto(self, *args, **kwargs): if self.visit: headers = kwargs.get('headers', {}) headers.update(cookie_header(self.visit)) kwargs['headers'] = headers testutil.createRequest(*args, **kwargs) if self.cookie_name in cherrypy.response.simple_cookie: self.visit = cherrypy.response.simple_cookie[self.cookie_name] self.response = cherrypy.response.body[0] self.status = cherrypy.response.status
Ideas and suggestions are welcome!
|
|
|