Как настроить тестовые данные и тестовые случаи в одном скрипте Python - PullRequest
0 голосов
/ 30 января 2019

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

Однако, когда я запускаю скрипт, он создает тестовые данные,но печатает сообщение об ошибке, что данные не существуют, что приводит к провалу теста.Только когда я снова запускаю скрипт, тест завершается успешно.

Ниже приведен упрощенный скрипт, который я написал, чтобы выяснить, что происходит.

import unittest
from ddt import ddt, file_data
import pandas

@ddt
class TestWhatever(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        cls.setup_test_data()
        print("setUpClass is running")

    @classmethod
    def tearDownClass(cls):
        print("tearDownClass is running")

    @classmethod
    def setup_test_data(cls):
        data = pandas.DataFrame({'msg':["testing"]})
        data = data.transpose()
        with open("practice_test.json", "w") as file:
           file.write(data.to_json())
        print("setup_test_data is running")

    @file_data("practice_test.json")
    def test_whatever_possible(self, msg):
        print("test_whatever_possible is running :", msg)
        self.assertEqual('q', 'q')

    def test_whatever_impossible(self):
        print("test_whatever_impossible is running")
        self.assertEqual('n', 'n')

Когда я запускаю скрипт выше,он печатает:

setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.EtearDownClass is running

======================================================================
ERROR: test_whatever_possible_00001_error (main.TestWhatever)
Error!
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\ddt.py", line 145, in wrapper
    return func(self, *args, **kwargs)
  File "C:\ddt.py", line 187, in func
    raise ValueError(message % file_attr)
ValueError: practice_test.json does not exist

----------------------------------------------------------------------
Ran 2 tests in 0.006s

FAILED (errors=1)

Затем при втором запуске:

setup_test_data is running
setUpClass is running
test_whatever_impossible is running
.test_whatever_possible is running : testing
.tearDownClass is running

----------------------------------------------------------------------
Ran 2 tests in 0.005s

OK

В этот момент я в значительной степени растерялся ... У кого-нибудь есть подсказка по этому поводу?

Ответы [ 2 ]

0 голосов
/ 30 января 2019

В качестве обходного пути вы можете написать собственный декоратор для создания файла данных, например,

def create_data(name):
    def decorator(fn):
        def decorated(*args, **kwargs):
            data = pandas.DataFrame({"msg": ["testing"]})
            data = data.transpose()
            with open(name, "w") as file:
                file.write(data.to_json())
            res = fn(*args, **kwargs)
            os.unlink(name)
            return res
        return decorated
    return decorator

, а затем сложить его для своего теста (и удалить шаг setup_test_data):

@ddt
class TestWhatever(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("setUpClass is running")

    @classmethod
    def tearDownClass(cls):
        print("tearDownClass is running")

    @create_data("practice_test.json")
    @file_data("practice_test.json")
    def test_whatever_possible(self):
        print("test_whatever_possible is running :")
        self.assertEqual("q", "q")

Обновление: 31 января

В следующем примере сохраняется поведение ddt при передаче значения параметра в тестовую функцию:

import json
import unittest
from ddt import ddt, FILE_ATTR


def create_file_data(value, data):
    def wrapper(func):
        with open(value, "w") as file:
            file.write(json.dumps(data))
        # this is what the file_data decorator does
        setattr(func, FILE_ATTR, value)
        return func

    return wrapper


@ddt
class TestWhatever(unittest.TestCase):
    @create_file_data("practice_test.json", {"msg": ["testing"]})
    def test_file_data(self, msg):
        print("test_file_data msg:", msg)


unittest.main()

При запуске выдается:

test_file_data msg: ['testing']
.
----------------------------------------------------------------------
Ran 1 test in 0.001s

Используя два приведенных выше примера, вы сможете найти подходящее решение для вашей проблемы.

0 голосов
/ 30 января 2019

Весь код Python является исполняемым.Когда тело класса загружается, операторы в нем выполняются.Декорированная функция создает функцию с кофе внутри def, присваивает ее имени (например, test_whatever_possible) во временном пространстве имен класса, а затем заменяет ее результатом вызова декоратора.

Это важно по той причине, что декоратор вызывается при загрузке класса, а не при запуске тестов.Декоратор file_data проверяет, существует ли файл прямо там и тогда (косвенно), поскольку он должен заменить вашу тестовую функцию на функцию, которая вызывает ваш тест со значениями в файле.

Ваш второй запуск пройден, потому что при первом запуске был создан тестовый файл.Я бы порекомендовал заполнить вопрос на GitHub.Либо file_data необходимо отложить открытие файла, либо непредвиденное поведение должно быть где-то четко задокументировано.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...