Pull to refresh

Comments 23

Мой глаз радуют любые статьи по Python/Django. Не останавливайтесь.
А как вы обходите проблему жестко прописанных параметров при POST запросах?
Я так и не нашел легкого и удачного решения.
Не уверен, что правильно понимаю вопрос. Для создания разных пользователей написал такую функцию, например:

def _create_user():
    username = ''.join(random.sample(string.lowercase, 8))
    email = username + '@gmail.com'
    password = username.upper()
    user = User.objects.create_user(**locals())
    user.data = {'username': username, 'password': password}
    return user

# и потом в коде
user = _create_user()
response = self.client.post(settings.LOGIN_URL, user.data)
...

Не венец творения, но работает.
Поясняю вопрос. У меня в приложении есть форма, которая динамически генерируется. Я сам с трудом понимаю какие там имена у полей формы. Да, и сами значения могут меняться у селектов, например.
Суть в том что я не могу написать тест, который не будет ломаться при каждой модификации кода, т.к. наименования полей и всякие другие условия меняются.
Минутка антирекламы, никого не хочу обидеть. Считайте, что я просто не научился их готовить. Селениум считаю слишком радикальным решением, twill инороден. Django-webtest неплохое решение, но тоже чем-то не устроил.
Вот и спрашиваю, что выбрать, дополнительно хотелось бы все таки обертку над стандартным django-unittest'ом.
Ох, я не уверен что так бывает. Можно смотреть, какие у сгенерированной формы есть поля, но если их назначение меняется, то непонятно, что с этой информацией дальше делать.
Вот пример из Django webtest в котором отражена проблема, поля берутся из формы. Например если у вас там свои какие-то проверки.
class AuthTest(WebTest):
    fixtures = ['users.json']
    def test_login(self)
        form = self.app.get(reverse('auth_login')).form
        form['username'] = 'foo'
        form['password'] = 'bar'
        response = form.submit().follow()
        self.assertEqual(response.context['user'].username, 'foo')

Вот я и думаю, может у кого-то есть рецепт более менее подходящий мне. Потому как я когда попробовал, понял что не так тут все просто.
думаю проблема не в django-webtest, а в том, что:
Я сам с трудом понимаю какие там имена у полей формы.

написание теста является одним из способов формализации требований. тест обязан ломаться, когда требования меняются и код рефачится — это фича. :)

если переделка кода вызывает ломку тестов, которые по логике не связанны с текущим рефакторингом, значит сами тесты составлены неправильно — проблема или в неправильно декомпозиции или в неправильно выбранном уровне абстракции. обычно это происходит, когда тест безосновательно пытается тестировать требования, которые не связаны с фичей, либо привязывается к каким-то низкоуровневым деталям реализации.
В свое время перешел на django-nose и django-webtest, внутренняя система тестирования не совсем то что требовалось, к примеру расположение всех тестов в отдельной папке, а не в каждом приложении по отдельности.
Разве http-клиент относится к юнит-тестам? Всегда считал это интеграционным тестом. Даже импорт для него в вашем примере указан не из django.utils.unittest.
Да, строго говоря, это интеграционный тест. В контексте веб-приложения выделить «чистые» юнит-тесты не всегда возможно.
Как правило, такое бывает, если писать тесты после кода ;)
Я для тестирования создаю sqlite базу прямо в памяти вот таким образом:

DATABASES = {
    'default': {
        #...           
    },

    # база для тестирования приложения
    'slave': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': ':memory:',
        'TEST_MIRROR': 'default', 
        # если не добавить эту строку, тесты не будут выполняться
        # бд, содержащаяся в памяти, не поддерживает транзакции
        'SUPPORTS_TRANSACTIONS': 'False',
    },
}
К сожалению, все так протестировать нельзя. У меня PostgreSQL и сложный проект: используются триггеры, хранимые процедуры, window functions (через raw sql, конечно). Каждый прогон тесто занимает несколько минут. :(
sqlite слишком многое прощает, когда-то кажется даже максимальная длина строки игнорировалась, да и с ключами постоянно какие-то непонятнки, в итоге на настоящем постгресе вылезали integirtyerror
Ну вот да, я это примерно имел в виду, когда писал, что лучше разрабатывать и тестировать в окружении, максимально близком к продакшену. Скажем, CharField(max_length=1024) можно сделать уникальным в PostgreSQL, но нельзя в MySQL (MyISAM).
> И сразу ложка дегтя: с Django 1.3 (и dev-версией) ни одно готовое решение для code coverage, похоже, не работает (поправьте меня, если это не так). Что, впрочем, не помешает нам запустить coverage.py руками.

C Django 1.3 у нас работает coverage 3.4 + django-coverage 1.0.3. С dev-версией нужно пробовать django-coverage 1.2 + coverage 3.4 или 3.5b1. Сам пока на dev-версии не пробовал настроить.
Надо попробовать, спасибо. Печально, что django-test-extensions никто не чинит, там CI-штука даже есть (runtester).
Пускалка (на языке оригинала — test runner) найдет юнит- и доктесты

Это поведение изменилось в Django 1.6:

Doctests will no longer be automatically discovered. To integrate doctests in your test suite, follow the recommendations in the Python documentation
Sign up to leave a comment.

Articles