Может ли модульный тест утверждать, что метод вызывает sys.exit ()

98

У меня есть метод python 2.7, который иногда вызывает

sys.exit(1) 

Можно ли сделать модульный тест, который проверяет, что эта строка кода вызывается при соблюдении правильных условий?

Медведь Трэвис
источник

Ответы:

155

Да. sys.exitрейзит SystemExit, так что вы можете проверить это с помощью assertRaises:

with self.assertRaises(SystemExit):
    your_method()

Экземпляры SystemExitимеют атрибут, для codeкоторого установлен предлагаемый статус выхода, а диспетчер контекста, возвращаемый с помощью, assertRaisesимеет экземпляр пойманного исключения as exception, поэтому проверить статус выхода легко:

with self.assertRaises(SystemExit) as cm:
    your_method()

self.assertEqual(cm.exception.code, 1)

 

sys.exit Документация :

Выход из Python. Это реализуется путем создания SystemExitисключения ... можно перехватить попытку выхода на внешнем уровне.

Павел Аносов
источник
3
+1, за исключением того, что если он хочет проверить, что он вызывает sys.exit(1)(в отличие от, скажем, sys.exit(0)), вам нужно фактически подтвердить, что он codeравен 1. Я думаю, вы могли бы сделать это с помощью assertRaisesRegexp(SystemExit, '1')?
abarnert
Я был уверен, что существует unittestметод, который позволяет передавать исключение и вызываемый предикат для выполнения для исключения или его аргументов, а не просто шаблон регулярного выражения для выполнения в строковом представлении его первого аргумента… но я думаю, что нет. Я думаю о каком-нибудь другом тестовом модуле?
abarnert
1
+1, что касается проверки кода ошибки, это гораздо проще сделать: self.assertRaisesRegex( SystemExit, '^2$', testMethod ) меньше кода, достаточно читабельна.
Марек Левандовски
1
@MarekLewandowski - опечатка. Должно бытьself.assertRaisesRegexp
Evgen
12

Вот полный рабочий пример. Несмотря на отличный ответ Павла, мне потребовалось время, чтобы понять это, поэтому я включаю его здесь в надежде, что он будет полезен.

import unittest
from glf.logtype.grinder.mapping_reader import MapReader

INCOMPLETE_MAPPING_FILE="test/data/incomplete.http.mapping"

class TestMapReader(unittest.TestCase):

    def test_get_tx_names_incomplete_mapping_file(self):
        map_reader = MapReader()
        with self.assertRaises(SystemExit) as cm:
            tx_names = map_reader.get_tx_names(INCOMPLETE_MAPPING_FILE)
        self.assertEqual(cm.exception.code, 1)
Медведь Трэвис
источник
3

Я нашел ответ на ваш вопрос в поисковой документации по модульному тестированию Python «Тестирование на исключения». Используя ваш пример, модульный тест будет выглядеть следующим образом:

self.assertRaises(SystemExit, your_function, argument 1, argument 2)

Не забудьте включить все аргументы, необходимые для проверки вашей функции.

сонный
источник
1

В качестве дополнительного примечания к отличному ответу Павла вы также можете проверить конкретные статусы, если они предусмотрены в функции, которую вы тестируете. Например, если он your_method()содержит следующее, sys.exit("Error")можно будет конкретно проверить "Ошибка":

with self.assertRaises(SystemExit) as cm:
    your_method()
    self.assertEqual(cm.exception, "Error")
бинарный субстрат
источник