在selenium中测试身份验证UI

时间:2011-01-12 17:21:31

标签: python authentication selenium pylons

我使用selenium和pylons来测试用户交互。一切都很好,直到我添加了身份验证UI测试 - 一个带有用户名和密码的登录屏幕。 Chrome(我在selenium下使用的浏览器)似乎弹出一个对话框来请求是否存储凭据。在此之后,所有测试都失败了。

有没有人有关于使用selenium和可能弹出对话框的身份验证/ UI的指示?我知道this selenium warning。 “不要这样做。反而做其他事情”将是一个可以接受的答案。


项目/测试/ LIB /硒/ login_page.py

"""
LoginPage represents the page where users are authenticated for the application
"""


class LoginPage(object):
    """This is the LoginPage class."""

    login = '/authentication/login'
    logout = '/authentication/logout'
    home = '/home'

    def __init__(self, browser):
        self._browser = browser

    def goto_login(self, baseurl):
        return self._browser.go_to(baseurl + self.login)

    def goto_logout(self, baseurl):
        return self._browser.go_to(baseurl + self.logout)

    def goto_home(self, baseurl):
        return self._browser.go_to(baseurl + self.home)

    def enter_credentials(self, username, password):
        element_by_id = self._browser.get_element_by_id
        element_by_id("login").value = username
        element_by_id("password").value = password

    def submit_form(self):
        element = self._browser.get_element_by_id('submit')
        return self._browser.click(element)

项目/测试/硒/ test_login_page.py

"""Tests the login page."""

import nose.tools as nt
from nose.plugins.skip import SkipTest

from assess.tests.selenium import SeleniumTestBase
from assess.tests.lib.selenium.login_page import LoginPage


class TestLoginPage(SeleniumTestBase):
    """Tests the login page."""

    def _login_page(self):
        return self.baseurl + '/authentication/login'

    def setUp(self):
        nt.set_trace()
        super(TestLoginPage, self).setUp()
        self.page = LoginPage(self.browser)

    def tearDown(self):
        super(TestLoginPage, self).tearDown()
        self.page = None

    def test_login_page_fail(self):
        # Logout before beginning test
        self.page.goto_logout(self.baseurl)

        self.page.goto_login(self.baseurl)
        nt.assert_true(self.browser.get_url().startswith(self._login_page()))
        self.page.enter_credentials('foo', 'random')
        self.page.submit_form()

    def test_login_page_success(self):
        # Logout before beginning test
        self.page.goto_logout(self.baseurl)

        self.page.goto_login(self.baseurl)
        nt.assert_true(self.browser.get_url().startswith(self._login_page()))
        self.page.enter_credentials('user', 'good-password')
        self.page.submit_form()

项目/模板/ login.html.mako

<%inherit file="/layout.html.mako" />

${h.stylesheet_link('login.css')}

<form action="/__do_login" method="POST">
    <fieldset>
        <p>
        <label for="login">User name</label><br />
        <input id="login" name="login" type="text" maxlength="40" value="" />
        </p>
        <p>
        <label for="password">Password</label><br />
        <input id="password" name="password" type="password" maxlength="40" value="" />
        </p>
        <p class="submit">
        <input id="submit" type="submit" value="Submit" />
        </p>
    </fieldset>
</form>

等/ who.ini

[general]
request_classifier = repoze.who.classifiers:default_request_classifier
challenge_decider = repoze.who.classifiers:default_challenge_decider

[identifiers]
plugins = foo
          friendly_form;browser

[authenticators]
plugins = foo 

[challengers]
plugins = friendly_form;browser
          foo

[plugin:foo]
use = ...
host = ...
logout_path_regex = /authentication/logout
httponly = True

[plugin:friendly_form]
use = repoze.who.plugins.friendlyform:FriendlyFormPlugin
login_form_url = /authentication/login
login_handler_path = /__do_login
post_login_url = /home
logout_handler_path = /authentication/logout
post_logout_url = /authentication/login

项目/配置/ routing.py

def make_map(config):
    """Create, configure and return the routes Mapper"""
    mapper = Mapper(directory=config['pylons.paths']['controllers'],
                 always_scan=config['debug'])
    mapper.minimization = False
    mapper.explicit = False

    # The ErrorController route (handles 404/500 error pages); it should
    # likely stay at the top, ensuring it can always be resolved
    mapper.connect('/error/{action}', controller='error')
    mapper.connect('/error/{action}/{sid}', controller='error')

    # CUSTOM ROUTES HERE

...
    mapper.connect('/authentication/login',
                   controller='authentication',
                   action='index')
    mapper.connect('/authentication/logout',
                   controller='authentication',
                   action='logout')

项目/控制器/ authentication.py

"""
This module contains the login controller.
"""

import logging

from pylons.controllers.util import redirect
from pylons import url, tmpl_context as c, request

from project.lib.base import BaseController
from project.lib.authorize import user_is_authenticated

logger = logging.getLogger(__name__)


class AuthenticationController(BaseController):
    """ This controller serves the login page."""
    template = '/login.html.mako'

    def index(self):
        return self.render(self.template)

    def validate(self):
        """ render a login page if we're not logged in """
        c.came_from = request.params.get("came_from", url("home"))

        # If we're already authenticated, redirect us to where we started.
        if user_is_authenticated():
            msg = "User is authenticated: redirecting to %s" % c.came_from
            logger.info(msg)
            redirect(c.came_from)

        msg = "User is not authenticated: rendering %s" % self.template
        logger.info(msg)
        return self.render(self.template)

项目/ LIB / authorize.py

''' Helper functions for the authorization and authentication mechanisms. '''
from pylons import request
from decorator import decorator
from pylons.controllers.util import abort


def user_is_authenticated():
    """ Returns True if is authenticated, else returns False.
    """
    identity = request.environ.get('repoze.who.identity')
    return identity and 'xxx' in identity


@decorator
def authenticated(func, *args, **kwargs):
    """ Check if is authenticated.  If not authenticated, abort with
        401 status.
    """
    if not user_is_authenticated():
        abort(401, 'You are not authenticated')
    return func(*args, **kwargs)

1 个答案:

答案 0 :(得分:1)

理想情况下,您应该使用配置文件进行测试,在此配置文件中,您应指定永远不要求保存凭据。遗憾的是,无法使用Selenium 1指定自定义Chrome配置文件,但可以在Selenium 1中为Firefox执行或移至Selenium 2(WebDriver) - 有关详细信息,请参阅this thread