Я пишу программное обеспечение, которое выполняет некоторый анализ входных данных и возвращает результат. Часть требований включает в себя, генерирует ноль или более предупреждений или ошибок и включает в себя те, которые в результате. Я также пишу модульные тесты, в которых, в частности, есть некоторые надуманные данные для проверки правильности выдачи предупреждений.
Мне нужно иметь возможность анализировать предупреждения / ошибки и проверять правильность выдачи ожидаемых сообщений. ,Я решил хранить сообщения в контейнере и ссылаться на них с идентификатором сообщения, который очень похож на то, как я делал локализацию в прошлом.
errormessages.py
сейчас выглядит примерно так:
from enum import IntEnum
NO_MESSAGE = ('')
HELLO = ('Hello, World')
GOODBYE = ('Goodbye')
class MsgId(IntEnum):
NO_MESSAGE = 0
HELLO = 1
GOODBYE = 2
Msg = {
MessageId.NO_MESSAGE: NO_MESSAGE,
MessageId.HELLO: HELLO,
MessageId.GOODBYE: GOODBYE,
}
Итак, анализ может выглядеть примерно так:
from errormessages import Msg, MsgId
def analyse(_):
errors = []
errors.append(Msg[MsgId.HELLO])
return _, errors
А в модульных тестах я могу сделать что-то похожее на
from errormessages import Msg, MsgId
from my import analyse
def test_hello():
_, errors = analyse('toy')
assert Msg[MsgId.HELLO] in errors
Но некоторые изсообщения форматируются, и я думаю, что это будет чертовски сложно при разборе сообщений для модульных тестов. Я думал, что добавлю ароматы сообщений;один для форматирования, а другой для разбора:
обновлено errormessages.py
:
from enum import IntEnum
import re
FORMAT_NO_MESSAGE = ('')
FORMAT_HELLO = ('Hello, {}')
FORMAT_GOODBYE = ('Goodbye')
PARSE_NO_MESSAGE = re.compile(r'^$')
PARSE_HELLO = re.compile(r'^Hello, (.*)$')
PARSE_GOODBYE = re.compile('^Goodbye$')
class MsgId(IntEnum):
NO_MESSAGE = 0
HELLO = 1
GOODBYE = 2
Msg = {
MessageId.NO_MESSAGE: (FORMAT_NO_MESSAGE, PARSE_NO_MESSAGE),
MessageId.HELLO: (FORMAT_HELLO, PARSE_HELLO),
MessageId.GOODBYE: (FORMAT_GOODBYE, PARSE_GOODBYE),
}
Так что анализ может выглядеть так:
from errormessages import Msg, MsgId
def analyse(_):
errors = []
errors.append(Msg[MsgId.HELLO][0].format('World'))
return _, errors
И в блокетесты, которые я могу сделать:
from errormessages import Msg, MsgId
from my import analyse
import re
def test_hello():
_, errors = analyse('toy')
expected = {v: [] for v in MsgId}
expected[MsgId.HELLO] = [
Msg[MsgId.HELLO][1].match(msg)
for msg in errors
]
for _,v in expected.items():
if _ == MsgId.HELLO:
assert v
else:
assert not v
Мне было интересно, есть ли способ лучше / проще? В частности, сообщения эффективно повторяются дважды;один раз для форматера и один раз для регулярного выражения. Есть ли способ использовать одну строку как для форматирования, так и для захвата регулярных выражений?