Как отключить переводы в тестах (django, pytest)
Это не совсем вопрос, а предложение решения проблемы. Я пытался найти статью, чтобы решить эту проблему, с которой я столкнулся, но в конце дня я действительно придумал что-то, что может помочь некоторым людям в той же ситуации, что и я:
Технологический стек: Django==2.2.x
, pytest==6.0.0
Проблема: Я попытался протестировать простую валидацию формы. Сравните сообщения об ошибках, возвращаемые при валидации формы, с ожидаемыми сообщениями, чтобы проверить, работает ли валидация так, как ожидалось.
class TestPassword:
@pytest.mark.parametrize(
'password,error_message',
[
('#noDigitPassword', 'At least one digit is required.'),
('#nouppercasep4ssword', 'At least one capital letter is required.'),
('#NOLOWERC4SEPASSWORD', 'At least one lower case letter is required.'),
('NoSymbolP4ssword', 'At least one special char (!%&@#$^*?_~.) is required.'),
('#WhitSpace P4ssword', 'Whitespaces are not allowed.'),
],
)
def test_form_password_complexity_check(self, password: str, error_message: str) -> None:
form = SignUpForm(
dict(
email="dummy@email.com",
first_name="dummy first_name",
last_name="dumy last_name",
password=password,
)
)
assert form.is_valid() is False
assert error_message in str(form.errors['password'])
class SignUpForm(forms.Form):
email = forms.CharField(max_length=255)
first_name = forms.CharField(max_length=255)
last_name = forms.CharField(max_length=255)
password = forms.CharField(
max_length=255,
validators=[
at_least_one_capital_case_validator,
at_least_one_lower_case_validator,
at_least_one_number_validator,
at_least_one_special_char_validator,
no_whitespaces_validator,
],
)
Сообщения об ошибках валидации используют ugettext_lazy и выводят следующие строки:
_("At least one lower case letter is required.")
_("At least one special char (!%&@#$^*?_~.) is required.")
_("At least one capital letter is required.")
_("At least one digit is required.")
_("Whitespaces are not allowed.")
Итак, django использует язык приложения по умолчанию во время тестирования. Что если строки в файлах *.po отличаются от строк в коде? Например:
msgid "At least one special char (!%&@#$^*?_~.) is required."
msgstr "At least one special character is required."
msgid "At least one capital letter is required."
msgstr "At least one uppercase letter is required."
Тест не работает для этих двух.
assert error_message in str(form.errors['password'])
# gives
"At least one capital letter is required." in "<ul class="errorlist"><li>At least one uppercase letter is required.</li></ul>"
# assertion fails
Совмещение строк в тестовом примере со строками в файлах *.po кажется неправильным. Так как переведенные строки могут измениться в будущем.
Использование Как отключить переводы во время модульных тестов в django? Я нашел решение, которое может быть полезным для этого.
Давайте создадим простой декоратор для отключения переводов для testcase:
def deactivate_translations(func: Callable) -> Callable:
@wraps(func)
def wrapper(*args, **kwargs):
translation.deactivate_all()
func(*args, **kwargs)
translation.activate(settings.LANGUAGE_CODE) # We need it to ensure our further tests which actually uses the language don't fail.
return wrapper
В итоге этот декоратор отключает использование *.po файлов для тесткейса и благодаря этому строки, которые должны быть переведены, используют сырой код вместо переведенной строки.
Если у вас есть идеи, как это можно сделать лучше, не утруждайте себя комментариями.