使用Recorder模块进行Kivy单元测试

时间:2016-10-31 05:31:52

标签: python unit-testing kivy

我试图为我的Kivy应用程序编写一些单元测试,似乎一个好的方法是使用记录器模块执行一些简单的操作然后声明添加/销毁相应的小部件(或者因为我正在使用存储模块,所以更新了DictStore。

我成功录制了录音,但我无法弄清楚如何运行我的应用并播放录音。我已经完成了相当多的谷歌搜索,但我似乎无法找到一个例子。这就是我到目前为止所拥有的:

from my_app import MyApp
from kivy.input.recorder import Recorder

def recorder_loop(instance, value):
    if value is False:
        instance.play = True

app = MyApp()
app.run()
rec = Recorder(filename='my_recorded_file.kvi')
rec.bind(play=recorder_loop)
rec.play = True
app.stop()

但是,我在这里很困惑。一旦我调用app.run(),似乎python等待来自应用程序的输入而不是执行记录器代码。那么,我该如何播放这段录音?

1 个答案:

答案 0 :(得分:2)

当然等了。应用程序只是一个无限循环,一遍又一遍地执行一些代码。如果没有处理输入,你甚至无法与它进行交互。想象一下它就像while True: pass

然而,应用程序的工作方式有所不同,如果您能够暂停"它可以让您从外部进行交互。无限循环,以便它可以获取你喜欢的任何东西。

尽管Recorder是一个相当不错的模块,但即使在编辑动作之间的时间之后,它也会超出测试范围,因此使用它必须有一个非常好的理由,否则它只是浪费资源和时间,在测试时很宝贵。

阅读我的"article"关于使用Kivy的单元测试,甚至还有一个运行多个测试的软件包(类似于鼻子,但更简单)。我并没有真正计划删除那个回购,但万一发生了什么事情:

import unittest

import os
import sys
import time
import os.path as op
from functools import partial
from kivy.clock import Clock

main_path = op.dirname(op.dirname(op.abspath(__file__)))
sys.path.append(main_path)

from main import My


class Test(unittest.TestCase):
    # sleep function that catches `dt` from Clock
    def pause(*args):
        time.sleep(0.000001)

    # main test function
    def run_test(self, app, *args):
        Clock.schedule_interval(self.pause, 0.000001)

        # Do something
        app.my_button.dispatch('on_release')
        self.assertEqual('Hello Test', app.my_button.text)
        #self.assertEqual('Fail Test', app.my_button.text)

        # Comment out if you are editing the test, it'll leave the
        # Window opened.
        app.stop()

    # same named function as the filename(!)
    def test_example(self):
        app = My()
        p = partial(self.run_test, app)
        Clock.schedule_once(p, 0.000001)
        app.run()

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

方法"暂停"从内部暂停应用程序的无限循环,让您可以轻松地与它进行交互。

让我们进入不那么令人愉快的部分。在测试时,您可能需要导航到某些小部件等等,但是在使用这种方式将所有内容放入App类以便于访问时会有一种冲动。不要这样做,你很快就会用完名字,这会让你的主要代码更加混乱。

虽然something.ids.<id>.children[1].ids. ...不是很好看,但它很方便,因为它可以让你看到你探究树的深度,你在哪里......你还可以把它放进去测试开始时的变量。在进行测试时,查看kv文件很方便,它使得遍历子树更容易编写。

随意查看my tests

更新:最近我从Tito那里看到了一些新东西,这肯定有助于更好地访问对象,而不是通过ids - Telenium