在Selenium中测试身份验证UI
我正在用selenium和pylons来测试用户的操作。一切都很顺利,直到我开始测试一个需要登录的界面——就是输入用户名和密码的登录屏幕。问题是,Chrome浏览器(我在selenium中使用的浏览器)弹出了一个对话框,询问是否要保存这些登录信息。之后,所有的测试都失败了。
有没有人能给我一些关于如何在selenium中处理需要身份验证的界面,特别是那些可能弹出对话框的界面的建议?我知道有一个关于selenium的警告,提到“不要这样做,应该这样做”。如果有人能给我这样的建议,那就太好了。
项目中的文件路径如下:
project/tests/lib/selenium/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)
project/tests/selenium/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()
project/templates/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>
etc/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
project/config/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')
project/controllers/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)
project/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 个回答
1
理想情况下,你应该为你的测试使用一个配置文件,并在这个配置文件中设置为永远不询问是否保存凭据。不过,遗憾的是,在Selenium 1中无法指定一个自定义的Chrome配置文件,但在Selenium 1中可以为Firefox做到这一点,或者你可以升级到Selenium 2(WebDriver) - 更多信息请查看这个讨论串