Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test command line scripts with nose?

I've created a Python library with some command-line scripts in a 'bin' directory (so that setup.py will install it into 'bin' when installing it with pip). Since this isn't a Python module, I can't work out how to test it with nose.

How can I test a command line script that's part of a library using nose/unittest?

like image 518
user1491250 Avatar asked Jun 04 '13 11:06

user1491250


People also ask

Which command is used to run nose tests?

nose can be integrated with DocTest by using with-doctest option in athe bove command line. The result will be true if the test run is successful, or false if it fails or raises an uncaught exception. nose supports fixtures (setup and teardown methods) at the package, module, class, and test level.

What is nose test Python?

Nose is a popular test automation framework in Python that extends unittest to make testing easier. The other advantages of using the Nose framework are the enablement of auto discovery of test cases and documentation collection.

Which of the following command is used to discover all tests in a project and execute them using nose?

pytest is capable of discovering and running tests written in unittest and nose. State true or false.


1 Answers

Use the "if __name__ == "__main__":" idiom in your scripts and encapsulate all of the function-ality in function-s.

Then you can import your scripts into another script (such as a unit test script) without the body of it being executed. This will allow you to write unit-tests for the functionality and run them through nose.

I recommend keeping the "main" block to a line or two.

For example:

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))

You can test command-line parameters, output, exceptions and return codes in your unittests...

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()

Output

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
like image 50
Johnsyweb Avatar answered Sep 28 '22 18:09

Johnsyweb