测试命令行工具

11 投票
4 回答
4496 浏览
提问于 2025-04-16 00:15

我在寻找一种方法,可以对用bash或其他语言编写的命令行工具进行测试。

我希望找到一个测试框架,里面可以有类似这样的语句:

setup:
    command = 'do_awesome_thing'
    filename = 'testfile'
    args = ['--with', 'extra_win', '--file', filename]
    run_command command args

test_output_was_correct
    assert_output_was 'Creating awesome file "' + filename + '" with extra win.'

test_file_contains_extra_win
    assert_file_contains filename 'extra win'

我想,基本的测试案例应该会设置一个临时目录,在这个目录里运行这些命令,然后在结束时把它删除。

我更倾向于使用Python,因为我对它比其他可能的语言更熟悉。

我想可能会有一些使用领域特定语言(DSL)的东西,这样就可以不受语言限制(或者说是它自己的语言,具体看你怎么理解);不过这可能不是最理想的,因为我的测试方法通常涉及编写生成测试的代码。

在网上搜索这个有点困难,因为关于运行测试的工具的信息很多,这和我想要的正好相反。

如果能支持在command --help的输出中嵌入文档测试,那就更好了 :)

4 个回答

1

我知道这个问题已经很久了,但因为我在找答案,所以决定分享一下我的解决方案,给其他碰到这个问题的人参考。

先说明一下:我提到的这个项目是我自己的,但它是完全免费的,还是开源的。

我遇到了一个非常相似的问题,最后自己做了一个解决方案。测试代码大概是这样的:

from CLITest import CLITest, TestSuite
from subprocess import CalledProcessError


class TestEchoPrintsToScreen(CLITest):
    '''Tests whether the string passed in is the string
    passed out'''

    def test_output_contains_input(self):
        self.assertNotIsInstance(self.output, CalledProcessError)
        self.assertIn("test", self.output)

    def test_ouput_equals_input(self):
        self.assertNotIsInstance(self.output, CalledProcessError)
        self.assertEqual("test", self.output)

suite = TestSuite()

suite.add_test(TestEchoPrintsToScreen("echo test"))

suite.run_tests()

这个方法让我解决了我的问题,但我知道它还有很多可以改进的地方,让它更稳定(比如测试发现功能)。希望这能帮到你,我也很喜欢收到好的建议和改进意见。

1

好吧……我们通常的做法(这也是面向对象编程语言的一个奇妙之处)是,在真正制作应用程序之前,先写好应用程序的所有组件。每个组件都可以独立运行,通常是在命令行中,这样你就可以把它们当作完整的程序来思考,并且在将来的项目中使用它们。如果你想测试一个现有程序的完整性……那么我觉得最好的办法就是深入了解它是怎么工作的,甚至更深入一点:阅读它的源代码。再深入一点:开发一个机器人来进行强制测试 :3

抱歉,这就是我能提供的了 .-.

13

可以看看 ScriptTest :

from scripttest import TestFileEnvironment

env = TestFileEnvironment('./scratch')

def test_script():
    env.reset()
    result = env.run('do_awesome_thing testfile --with extra_win --file %s' % filename)
    # or use a list like ['do_awesome_thing', 'testfile', ...]
    assert result.stdout.startswith('Creating awesome file')
    assert filename in result.files_created

它也可以很方便地用来做 doctest 测试。

撰写回答