5

我在“bin”目录中创建了一个带有一些命令行脚本的 Python 库(这样在使用setup.py安装时会将其安装到“bin”中pip)。由于这不是 Python 模块,我无法弄清楚如何用鼻子测试它。

如何使用nose/测试属于库的命令行脚本unittest

4

1 回答 1

11

在您的脚本中使用“ if __name__ == "__main__":”习语,并将所有功能性封装在功能-s中。

然后,您可以import将您的脚本放入另一个脚本(例如单元测试脚本),而无需执行它的主体。这将允许您为功能编写单元测试并通过nose.

我建议将“主要”块保持在一两行。

例如:

plus_one.py

#!/usr/bin/env python

import sys


def main(args):
    try:
        output(plus_one(get_number(args)))
    except (IndexError, ValueError), e:
        print e
        return 1
    return 0


def get_number(args):
    return int(args[1])


def plus_one(number):
    return number + 1


def output(some_text):
    print some_text


if __name__ == '__main__':
    sys.exit(main(sys.argv))

您可以在单元测试中测试命令行参数、输出、异常和返回码...

t_plus_one.py

#!/usr/bin/env python

from StringIO import StringIO
import plus_one
import unittest


class TestPlusOne(unittest.TestCase):

    def test_main_returns_zero_on_success(self):
        self.assertEquals(plus_one.main(['test', '1']), 0)

    def test_main_returns_nonzero_on_error(self):
        self.assertNotEqual(plus_one.main(['test']), 0)

    def test_get_number_returns_second_list_element_as_integer(self):
        self.assertEquals(plus_one.get_number(['anything', 42]), 42)

    def test_get_number_raises_value_error_with_string(self):
        self.assertRaises(ValueError, plus_one.get_number, ['something',
                                                            'forty-two'])

    def test_get_number_raises_index_error_with_too_few_arguments(self):
        self.assertRaises(IndexError, plus_one.get_number, ['nothing'])

    def test_plus_one_adds_one_to_number(self):
        self.assertEquals(plus_one.plus_one(1), 2)

    def test_output_prints_input(self):
        saved_stdout, plus_one.sys.stdout = plus_one.sys.stdout, StringIO('_')
        plus_one.output('some_text')
        self.assertEquals(plus_one.sys.stdout.getvalue(), 'some_text\n')
        plus_one.sys.stdout = saved_stdout

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

输出

python plus_one.py 41

42

nosetests -v t_plus_one.py

test_get_number_raises_index_error_with_too_few_arguments (t_plus_one.TestPlusOne) ... ok
test_get_number_raises_value_error_with_string (t_plus_one.TestPlusOne) ... ok
test_get_number_returns_second_list_element_as_integer (t_plus_one.TestPlusOne) ... ok
test_main_returns_nonzero_on_error (t_plus_one.TestPlusOne) ... ok
test_main_returns_zero_on_success (t_plus_one.TestPlusOne) ... ok
test_output_prints_input (t_plus_one.TestPlusOne) ... ok
test_plus_one_adds_one_to_number (t_plus_one.TestPlusOne) ... ok

----------------------------------------------------------------------
Ran 7 tests in 0.002s

OK
于 2013-06-04T11:47:08.690 回答