2014-04-16 7 views
5

Я пытаюсь добавить тесты в основное приложение. Доступ ко всем требует входа в систему.(unittest) Тестирование Flask-Security: не удается пройти страницу входа

Вот мой тест класс:

class MyAppTestCase(FlaskTestCaseMixin): 

    def _create_app(self): 
     raise NotImplementedError 

    def _create_fixtures(self): 
     self.user = EmployeeFactory() 

    def setUp(self): 
     super(MyAppTestCase, self).setUp() 
     self.app = self._create_app() 
     self.client = self.app.test_client() 
     self.app_context = self.app.app_context() 
     self.app_context.push() 
     db.create_all() 
     self._create_fixtures() 
     self._create_csrf_token() 

    def tearDown(self): 
     super(MyAppTestCase, self).tearDown() 
     db.drop_all() 
     self.app_context.pop() 

    def _post(self, route, data=None, content_type=None, follow_redirects=True, headers=None): 
     content_type = content_type or 'application/x-www-form-urlencoded' 
     return self.client.post(route, data=data, follow_redirects=follow_redirects, content_type=content_type, headers=headers) 

    def _login(self, email=None, password=None): 
     email = email or self.user.email 
     password = password or 'password' 
     data = { 
      'email': email, 
      'password': password, 
      'remember': 'y' 
      } 
     return self._post('/login', data=data) 


class MyFrontendTestCase(MyAppTestCase): 

    def _create_app(self): 
     return create_app(settings) 

    def setUp(self): 
     super(MyFrontendTestCase, self).setUp() 
     self._login() 

Я бегу мои тесты используют nosetests в Терминале так: source my_env/bin/activate && nosetests --exe

Основные тесты, как они не в состоянии:

class CoolTestCase(MyFrontendTestCase): 

    def test_logged_in(self): 
     r = self._login() 
     self.assertIn('MyAppName', r.data) 

    def test_authenticated_access(self): 
     r = self.get('/myroute/') 
     self.assertIn('MyAppName', r.data) 

С выхода , Я вижу, что r.data - это всего лишь HTML-адрес страницы входа без ошибок (например, неправильное имя пользователя или пароль) или предупреждения («Пожалуйста, войдите, чтобы получить доступ к этому страница ").

Я входе в течение setUp процесса, так test_authenticated_accessдолжны позволить мне либо доступ /myroute/ или перенаправить меня на страницу входа в систему с мелькнуло сообщение «Пожалуйста, войдите, чтобы получить доступ к этой странице». Но это не так.

Я не могу понять, что случилось. Я основано мое испытание прочь те, которые я нашел в Колба документации и this app boilerplate

+0

Я вижу, что вы используете CSRF токены - вы пробовали отключить их и увидеть, если это получает вас дальше? Я знаю, что они укусили меня в тестах больше времени, чем я помню. –

+0

Если вы используете (или можете использовать) Flask 0.10, я настоятельно рекомендую просто использовать новый поддельный контекстный материал: http://flask.pocoo.org/docs/testing/#faking-resources-and-context Мы в настоящее время делает что-то очень похожее на то, что вы делаете для наших тестов, и как только мы сможем обновиться, я все это разорву в пользу этого. –

+0

@RachelSanders - у меня уже есть 'WTF_CSRF_ENABLED', установленный на' False' –

ответ

2

я, наконец, понял это после того, как неделю убиваю себя ...

Существовали несколько проблем:

  1. Там это конфликт между Flask-Security и Flask-SSLify. Хотя автоматическое перенаправление https прекрасно работает на реальном веб-сервере, в тестах он полностью предотвращает вход в систему. Я понял это, создав поддельные тестовые маршруты и пытаясь получить POST случайных данных. В тестовом клиенте работало POST. Чтобы исправить это, мне пришлось изменить конфигурацию теста DEBUG на True. Обратите внимание, что это не очень удобное решение, поскольку такие вещи, как CSS и JS, не будут скомпилированы, а поведение другого приложения может быть другим ...

  2. Flask-Security не работает с factory_boy (или я не использовал factory_boy правильно?). Я пытался создать пользователей и роли через factory_boy, потому что я видел пример учебника, который использовал его. После того, как я исправил вышеуказанную проблему, он все время говорил мне, что пользователь не существует. Я закончил кражу кода из собственных тестов Flask-Security для создания поддельных пользователей с разными ролями.

Проблемный код:

session = db.create_scoped_session() 

class RoleFactory(SQLAlchemyModelFactory): 
    FACTORY_FOR = Role 
    FACTORY_SESSION = session 

    id = Sequence(int) 
    name = 'admin' 
    description = 'Administrator' 


class EmployeeFactory(SQLAlchemyModelFactory): 
    FACTORY_FOR = Employee 
    FACTORY_SESSION = session 

    id = Sequence(int) 
    email = Sequence(lambda n: 'user{0}@app.com'.format(n)) 
    password = LazyAttribute(lambda a: encrypt_password('password')) 
    username = Sequence(lambda n: 'user{0}'.format(n)) 
    #last_login_at = datetime.utcnow() 
    #current_login_at = datetime.utcnow() 
    last_login_ip = '127.0.0.1' 
    current_login_ip = '127.0.0.1' 
    login_count = 1 
    roles = LazyAttribute(lambda _: [RoleFactory()]) 
    active = True 

Это был мой тест:

class MyAppTestCase(FlaskTestCaseMixin, MyTestCase): 

    def _create_app(self): 
     raise NotImplementedError 

    def _create_fixtures(self): 
     #self.user = EmployeeFactory() 
     populate_data(1) 

    def setUp(self): 
     super(MyAppTestCase, self).setUp() 
     self.app = self._create_app() 
     self.client = self.app.test_client() 
     self.app_context = self.app.app_context() 
     self.app_context.push() 
     db.create_all() 
     self._create_fixtures() 
     self._create_csrf_token() 

    def tearDown(self): 
     super(MyAppTestCase, self).tearDown() 
     db.drop_all() 
     self.app_context.pop() 

    def _post(self, route, data=None, content_type=None, follow_redirects=True, headers=None): 
     content_type = content_type or 'application/x-www-form-urlencoded' 
     return self.client.post(route, data=data, follow_redirects=follow_redirects, content_type=content_type, headers=headers) 

    def _login(self, email=None, password=None): 
     email = email or '[email protected]' #self.user.email 
     password = password or 'password' 
     data = { 
      'email': email, 
      'password': password, 
      'remember': 'y' 
      } 
     return self._post('/login', data=data) 
+0

вы указали тест проблемы, но не рабочий тест. Нелегко найти его здесь. https://github.com/mattupstate/flask-security – nycynik

1

У меня была проблема с входа/выхода из системы на тестах с Колба-Security (который использует Flask- Login). Я решил эту проблему, издеваясь над функцией flask_login._get_user и установив app.login_manager._login_disabled в True.

Контекст менеджер, который издевается пользователь:

class LoginLogoutMixin(object): 
    @contextmanager 
    def login(self, user): 
     mock_get_user = patch('flask_login._get_user', Mock(return_value=user)) 
     self.app.login_manager._login_disabled = True 
     mock_get_user.start() 
     yield 
     mock_get_user.stop() 
     self.app.login_manager._login_disabled = False 

И пример это использование:

class ProtectedViewTestCase(LoginLogoutMixin, TestCase): 

    def setUp(self): 
     super(ProtectedViewTestCase, self).setUp() 
     # create user here 

    def test_protected_view(self): 
     with self.login(self.user): 
      rv = self.client.get(url_for('protected_view')) 
      self.assert200(rv)