【发布时间】:2011-01-12 17:21:30
【问题描述】:
我正在使用 selenium 和 pylons 来测试用户交互。一切都很好,直到我添加了对身份验证 UI 的测试——一个带有用户名和密码的登录屏幕。似乎 Chrome(我在 selenium 下使用的浏览器)正在弹出一个对话框,请求是否存储凭据。此后所有测试均失败。
是否有人对使用 selenium 和可能弹出对话框的身份验证/UI 有任何指示?我知道this selenium warning。 “不要这样做。改为做其他事情”将是一个可以接受的答案。
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()
项目/模板/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)
项目/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)
【问题讨论】:
-
Chrome 通常不会在页面顶部打开一个带有“保存密码”或“从不用于此站点”按钮的栏吗?这些是本机控件,所以没什么可做的。您是否找到了弹出阻止对话框的网站?
-
这不是一个阻塞对话框,但 selenium 似乎在 chrome 中创建了一个新选项卡,并且所有后续测试都失败了,因为 selenium 找不到要按下的按钮、输入元素以输入文本等。我相信在我的开发机器上,我一定说过“永远不要使用这个站点”(我什至认为这没有帮助),但我们运行的测试构建服务器肯定没有。真的很烦人。
-
这将是一个新问题,您能否将相关代码粘贴到您的问题中。我假设您使用的是 Selenium-RC 和 python?
-
添加了代码。一般要点是 pylons 在中间件中使用 repoze.who 进行身份验证。 who.ini 中的代码插入 url。 controllers.py 中的代码将 url 与控制器代码相关联。控制器代码使用 repoze.who 原语来确定身份验证。 Selenium 测试在显示登录屏幕时使用 Web 原语来驱动 Web UI,在使用正确的凭据时生成经过身份验证的用户。但是,结果是 selenium 在 chrome 中添加了额外的选项卡,使进一步测试中的 UI 元素无法访问。
标签: python authentication selenium pylons