机器人(Bots)

机器人模拟参与人游玩你的应用。它们点击按钮,填写表单,确保一切运行正常。

这一特性是为那些希望oTree能够自动测试他们应用的懒人设计的。并且oTree Studio甚至可以为你设计模拟代码,使得整个过程(编写和运行机器人程序)变得非常容易。

运行bots

  • 将bots添加到你的应用中(参考下面的代码)
  • 在你的session config中,设置 use_browser_bots=True.
  • 运行服务器并创建一个会话。一旦开始链接被打开,页面会使用浏览器bots自动进行。
  • 如果你使用了Heroku,确保第二个dyno被启用。

编写测试

在oTree Studio中,前往你应用的“Test”部分。单击按钮以自动编写bots代码。如果你想要改进生成的代码(比如加入 expect() 语句),阅读下面的部分。

如果你使用的是文本编辑器,前往 tests.py.

提交页面

你应当对每一个页面子任务创建一个 yield ,例如:

yield pages.Start
yield pages.Survey, dict(name="Bob", age=20)

这里,我们首先提交 Start 页面,它不包含任何表单。下一个页面有2个表单字段,故我们提交一个字典。

测试系统会抛出一个错误如果机器人提交了不正确的输入,或是按照错误的顺序提交了页面。

你可以使用 if 语句来判断角色或者轮数。举例如下:

if self.round_number == 1:
    yield pages.Introduction
if self.player.id_in_group == 1:
    yield pages.Offer, dict(offer=30)
else:
    yield pages.Accept, dict(offer_accepted=True)

你的 if 语句可以依赖 self.player, self.group, self.round_number, 诸如此类。

编写bots时请忽略等待页面。

轮次

你的bot代码应当每次仅模拟一轮。oTree会自动将其执行 num_rounds 次。

expect()

注解

expect() 函数在2019年12月被引入。在此之前我们推荐使用 assert 语句,这仍然可用,但是 expect() 可以更加清楚地报告错误。

你可以使用 expect 语句来确保你的代码如你期望地那样工作。

例如:

from otree.api import expect

expect(self.player.num_apples, 100)
yield pages.Eat, dict(apples_eaten=1)
expect(self.player.num_apples, 99)
yield pages.SomeOtherPage

如果 self.player.num_apples 不是99,那么你就会被提示有一个错误。

你也可以在expect中使用3个参数,如 expect(self.player.budget, '<', 100).这会验证 self.player.budget 比100小。你可以使用下面的这些运算符: '<', '<=', '==', '>=', '>', '!=', 'in', 'not in'.

测试表单验证

如果你使用了 form validation,你应当测试你的应用是否正确地防止了来自用户的错误输入,测试可通过 SubmissionMustFail() 进行。

例如你的页面如下:

class MyPage(Page):

    form_model = 'player'
    form_fields = ['int1', 'int2']

    @staticmethod
    def error_message(player, values):
        if values["int1"] + values["int2"] != 100:
            return 'The numbers must add up to 100'

下面的代码测试了它是否正常工作:

from otree.api import SubmissionMustFail

yield SubmissionMustFail(pages.MyPage, dict(int1=99, int2=0))
yield pages.MyPage, dict(int1=99, int2=1)

Bot会提交 MyPage 两次。如果第一次提交 成功,那么一个错误会抛出,因为这本不应该成功。

检查HTML

self.html 包含了你所要提交页面的HTML。你可以将其与 expect() 一起使用:

from otree.api import expect

if self.player.id_in_group == 1:
    expect(self.player.is_winner, True)
    print(self.html)
    expect('you won the game', 'in', self.html)
else:
    expect(self.player.is_winner, False)
    expect('you did not win', 'in', self.html)
yield pages.Results
# etc...

self.html 在每一个 yield 语句之后被更新为下一个页面的HTML。换行符与多余的空格会被忽略。

自动HTML检查

如果bot试图提交一个在页面HTML实际上不存在的表单或者页面HTML缺少了提交按钮,一个错误会被抛出。

然而,bot系统并不能识别被JavaScript动态添加的字段和按钮。在这种情况下,你应当禁用HTML检查,即设置 check_html=False。例如,修改下面的代码:

yield pages.MyPage, dict(foo=99)

为:

from otree.api import Submission
yield Submission(pages.MyPage, dict(foo=99), check_html=False)

(如果你在 Submission 中不设置 check_html=False, 那么两段代码是等价的。)

模拟页面超时

你可以在 Submission 中设置 timeout_happened=True:

from otree.api import Submission
yield Submission(pages.MyPage, dict(foo=99), timeout_happened=True)

高级特性

参见 Bots: 高级特性