Django测试:如何在SQLite上测试并发用户?

时间:2014-10-24 18:14:05

标签: python django sqlite integration-testing

我的Django webapps是多玩家策略游戏,涉及玩家通过一系列页面并在每个页面上提交ModelForm。它们通常是来回游戏,因此玩家1在玩家2看到等待屏幕时做出决定,反之亦然等等。游戏可以有不同数量的玩家。

我已经使用Django的HTTP测试客户端实现了测试,其中测试设计为从单个用户的角度编写,条件逻辑分支客户端是作为P1还是P2播放,并且等待屏幕被抽象掉:

def play(self):

    self.submit(views.Introduction)
    self.submit(views.Question1, {'answer': random.choice([True,False])})

    if self.player.id_in_group == 1:
        self.submit(views.Send, {"sent_amount": 4})
    else:
        self.submit(views.SendBack, {'sent_back_amount': 8})

    self.submit(views.Results)
    self.submit(views.Question2, dict(feedback=4))

然后,为了模拟N个玩家,我实例化N个线程,每个线程执行上面的代码。

这种方法适用于Postgres,但不适用于SQLite,由于外部原因,它是我们需要用于本地开发的引擎。我得到:OperationalError: Database is locked

有没有办法避免锁?像任务队列一样,或者在SQlite DB解锁之前一直睡觉?或者以某种方式以随机顺序循环遍历测试客户端并在给定时间从每个客户端执行几行?如果我们在SQLite上稍微降低性能,那就没关系。

注意:我可以编写内联多个播放器的代码,这样它们都可以在1个线程中执行,但是(1)我发现代码更难以阅读,(2)它是人为的,因为它硬编码了一个确切的动作顺序将被执行,并且(3)当我们将10人游戏改为20人游戏时,它不能很好地扩展。

1 个答案:

答案 0 :(得分:0)

SQLite支持multi threaded mode。在这种模式下,多个线程可以安全地使用SQLite,前提是在两个或多个线程中不同时使用单个数据库连接。

Celery提供了一种确保only one task runs at a time的方法。如果芹菜用于数据库事务,那么celery确保一次只允许一个事务运行,这可以解决您的问题。