oldboy

Недавно решил заняться отделением тестовых данных в коде от реальных тестовых сущностей в тестируемом приложении. Зачем?  Это хорошая практика, несколько упрощающая работу с Grail, который используется для написания тестовых шагов в WG.

Знающие пацаны посоветовали мне отличный Фреймворк для создания тестовых фикстур под названием factory_boy, про основные функции которого и расскажу.

Если верить официальному сайту Фреймворка, то это руби  Фреймворк factory_girl, переписанный для питона. Он предоставляет функционал для создания фабрик, упрощающих динамическое создание тестовых данных и, как вишенка на торте, позволяет использовать эту штуку вместо Django fixtures! БЕЗ РЕГИСТРАЦИИ И СМС!!!! Но про это есть много статей, я же рассмотрю функции, которые могут быть полезны рядовому автоматизированному тестировщику на python.

Предположим, что у нас есть класс, описывающий пользователя:

  1. class Account(object):
  2. def __init__(self, first_name, last_name, login, password, is_banned):
  3. self.first_name = first_name
  4. self.last_name = last_name
  5. self.login = login
  6. self.password = password
  7. self.is_banned = is_banned
  8.  
  9. def __str__(self):
  10. return 'Account[first_name={0}, last_name={1}, login={2}, password={3}, is_banned={4}]'.format(
  11. self.first_name,
  12. self.last_name,
  13. self.login,
  14. self.password,
  15. self.is_banned,
  16. )

Можно написать свои методы генерации случайных данных и в тестах создавать юзера так:

  1. def get_user():
  2. return Account(
  3. first_name=get_random_string(),
  4. last_name=get_random_string(),
  5. login=get_random_string(),
  6. password=get_random_string(),
  7. is_banned=False
  8. )
  9.  
  10.  
  11. def get_random_string(size=5):
  12. return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(size))

Но зачем, когда есть factory_boy? Можно сделать так:

  1. fake = Faker()
  2.  
  3.  
  4. class AccFactory(factory.Factory):
  5. class Meta:
  6. model = Account
  7.  
  8. @factory.lazy_attribute
  9. def first_name(self):
  10. return fake.first_name()
  11.  
  12. @factory.lazy_attribute
  13. def last_name(self):
  14. return fake.last_name()
  15.  
  16. login = factory.LazyAttribute(lambda o: '%s@example.org' % o.first_name)
  17. password = 'password'
  18. is_banned = False

Смотрится круто? А то! Причём данные по имени и фамили будут изменятся при создании каждого нового пользователя.

  1. print AccFactory()
  2. print
  3. print AccFactory(password='new_password', is_banned=True)
  4. print
  5. print get_user()

  1. Account[first_name=Norton, last_name=Kuhic, login=Norton@example.org, password=password, is_banned=False]
  2.  
  3. Account[first_name=Trevon, last_name=Schultz, login=Trevon@example.org, password=new_password, is_banned=True]
  4.  
  5. Account[first_name=4H0N0, last_name=PZCHI, login=UJO47, password=J3RH6, is_banned=False]

Для такой штуки в factory_boy есть следующие фичи:

  • Fuzzy attributes –для всякого рода создания случайных значений;
  • Faker – создание случайных осмысленных данных;
  • LazyAttribute – создание атрибута на основе другого атрибута;
  • Sequence – для генерации каждый раз уникального атрибута;
  • LazyAttributeSequence – смесь двух прошлых;
  • SubFactory – для вызова фабрики из другой фабрики;
  • SelfAttribute – для того, чтобы один атрибут ссылался на другой.

И это далеко не все фишки. ЧИТАЙТЕ ОФИЦИАЛЬНУЮ СТРАНИЦУ ПРОЕКТА.

Опубликовать в Google Plus
Опубликовать в LiveJournal
Опубликовать в Мой Мир
Опубликовать в Одноклассники
Опубликовать в Яндекс