我正在尝试使用Selenium为Django项目运行功能测试。在Firefox和Chrome上,当我尝试测试超级用户可以将普通用户的状态更改为工作人员时,我得到一个奇怪的外键错误(我假设这都是通过Django的内部测试验证的,但是认为包括这样做是好的做法它在我的应用程序测试中,因为我的用户场景取决于功能)。看起来Django几乎不喜欢Selenium将任何内容保存到数据库中?这个错误也会逐渐渗透到我的其他测试中,所以看起来像是在幕后打破了一些东西 - 比如Selenium失去了它的数据库连接。有谁知道为什么会这样?我愿意放弃测试以支持假设功能正常,但是我很乐意解决这个问题并使用测试。
一个可能的症状是,在Chrome中,在“选中框”和“单击保存按钮”的输出之间,我得到了一个损坏的管道(在Firefox中不会发生)。
每当Selenium点击“保存”按钮时,它似乎在这里徘徊:
# Form looks properly rendered, now click the 'Staff status'
# checkbox and submit it
isStaffCheckbox = self.browser.find_element_by_id('id_is_staff')
isStaffCheckbox.click()
print 'checked the box'
# Save the form
saveBtn = self.browser.find_element_by_css_selector('input[value="Save"]')
saveBtn.click()
print 'clicked the save button'
我得到的错误信息是:
Traceback (most recent call last):
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/test/testcases.py", line 268, in __call__
self._post_teardown()
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/test/testcases.py", line 533, in _post_teardown
self._fixture_teardown()
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/test/testcases.py", line 553, in _fixture_teardown
skip_validation=True, reset_sequences=False)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/__init__.py", line 161, in call_command
return klass.execute(*args, **defaults)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/base.py", line 255, in execute
output = self.handle(*args, **options)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/base.py", line 385, in handle
return self.handle_noargs(**options)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/commands/flush.py", line 82, in handle_noargs
emit_post_sync_signal(set(all_models), verbosity, interactive, db)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/sql.py", line 195, in emit_post_sync_signal
interactive=interactive, db=db)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/dispatch/dispatcher.py", line 170, in send
response = receiver(signal=self, sender=sender, **named)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/contrib/auth/management/__init__.py", line 96, in create_permissions
auth_app.Permission.objects.using(db).bulk_create(perms)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/models/query.py", line 444, in bulk_create
self._batched_insert(objs_without_pk, fields, batch_size)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/models/query.py", line 902, in _batched_insert
using=self.db)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/models/manager.py", line 215, in _insert
return insert_query(self.model, objs, fields, **kwargs)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/models/query.py", line 1661, in insert_query
return query.get_compiler(using=using).execute_sql(return_id)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 937, in execute_sql
cursor.execute(sql, params)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 122, in execute
six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 120, in execute
return self.cursor.execute(query, args)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.8-intel.egg/MySQLdb/cursors.py", line 202, in execute
self.errorhandler(self, exc, value)
File "~/virtual_environments/VideoSearch/lib/python2.7/site-packages/MySQL_python-1.2.4b4-py2.7-macosx-10.8-intel.egg/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`test_videos2002`.`auth_permission`, CONSTRAINT `content_type_id_refs_id_d043b34a` FOREIGN KEY (`content_type_id`) REFERENCES `django_content_type` (`id`))')
===== 更新了代码
感谢您的关注!
来自我的functional_tests.test.py(借鉴https://github.com/lincolnloop/django-selenium-intro/tree/master/selenium_intro):
from django.test import LiveServerTestCase
class SeleniumTestCase(LiveServerTestCase):
"""
A base test case for selenium, providing hepler methods for generating
clients and logging in profiles.
"""
def open(self, url):
self.browser.get("%s%s" % (self.live_server_url, url))
来自我的admin_django.py(一组测试用例)
from functional_tests.test import SeleniumTestCase
from selenium.webdriver.common.keys import Keys
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.test import LiveServerTestCase
from django.conf import settings
from selenium import webdriver
class AdminDjango(SeleniumTestCase):
def setUp(self):
User.objects.create_superuser(username='vcb',
password='rock5!',
email='me@name.edu')
User.objects.create_user(username='teaching',
password='assistant',
email='ta@name.edu')
# self.browser = webdriver.Chrome(settings.SELENIUM_WEBDRIVER)
self.browser = webdriver.Firefox()
self.browser.implicitly_wait(3)
self.browser.set_page_load_timeout(10)
def tearDown(self):
self.browser.quit()
def check_for_links(self, link_text):
"""
Helper function to check links on a page for certain text
"""
links = self.browser.find_elements_by_tag_name('a')
self.assertTrue(link_text, [link.text for link in links])
def admin_logs_in(self):
"""
Helper function that logs the admin user into the page
"""
username_field = self.browser.find_element_by_name('username')
username_field.send_keys('vcb')
password_field = self.browser.find_element_by_name('password')
password_field.send_keys('rock5!')
password_field.send_keys(Keys.RETURN)
def admin_log_in_complete(self):
"""
Includes navigation to the admin page
"""
self.open('/admin/')
self.admin_logs_in()
def test_admin_can_login(self):
"""
Admin user can log into the Django admin interface
"""
self.open('/admin/')
body = self.browser.find_element_by_tag_name('body')
self.assertIn('VCB Administration', body.text)
self.admin_logs_in()
# her username and password are accepted, and she is taken to
# the Site Administration page
body = self.browser.find_element_by_tag_name('body')
self.assertIn('Site administration', body.text)
def test_admin_page_renders_properly(self):
"""
The admin page should have at least two fields:
- Users
- Classes
Admins may have to add staff status to users, and they may have to
adjust the information for a class
"""
self.admin_log_in_complete()
self.check_for_links('Users')
self.check_for_links('Groups')
self.check_for_links('Classess')
def test_admin_can_make_a_user_staff(self):
"""
Admin users can add staff status to existing users
"""
self.admin_log_in_complete()
pageLinks = self.browser.find_elements_by_tag_name('a')
for link in pageLinks:
if link.text == 'Users':
userLink = link
userLink.click()
headers = self.browser.find_elements_by_tag_name('h1')
self.assertTrue('Select user to change',
[header.text for header in headers])
users = self.browser.find_elements_by_xpath('//table[@id="result_list"]/tbody/tr/th/a')
self.fail('Finish writing the test!')
# rowCount = 1
# for user in users:
# xpath = '//table[@id="result_list"]/tbody/tr[' + str(rowCount) + ']/td[5]/img'
# # check first that this user is not a staff
# staffIcon = self.browser.find_element_by_xpath(xpath)
# isStaff = staffIcon.get_attribute('alt')
#
# if isStaff == 'false':
# user.click()
# userHeaders = self.browser.find_elements_by_tag_name('h1')
# self.assertTrue('Change user',
# [userHeader.text for userHeader in userHeaders])
#
# # Are the right fields present in the user's form?
# formHeaders = self.browser.find_elements_by_tag_name('h2')
# self.assertTrue('Personal info',
# [formHeader.text for formHeader in formHeaders])
# self.assertTrue('Permissions',
# [formHeader.text for formHeader in formHeaders])
# self.assertTrue('Important dates',
# [formHeader.text for formHeader in formHeaders])
#
# # Form looks properly rendered, now click the 'Staff status'
# # checkbox and submit it
# isStaffCheckbox = self.browser.find_element_by_id('id_is_staff')
# isStaffCheckbox.click()
# print 'checked the box'
# # Save the form
# saveBtn = self.browser.find_element_by_css_selector('input[value="Save"]')
# saveBtn.click()
# print 'clicked the save button'
# # Returns you to the admin page
# messageBox = self.browser.find_element_by_class_name('info')
# self.assertIn('successfully', messageBox.text)
#
# # Check that staff status changed
# staffIcon = self.browser.find_element_by_xpath('//table[@id="result_list"]/tbody/tr[' + str(rowCount) + ']/td[5]/img')
# isStaff = staffIcon.get_attribute('alt')
# self.assertTrue(isStaff)
# print 'should now be staff'
# rowCount += 1
def test_admin_can_change_a_class_obj_bank_id(self):
"""
Admin users can change a class's objective bank id
"""
self.fail('Finish writing the test!')
def test_logging_out_redirects_to_login_page(self):
"""
Logging out of the admin page should redirect to the main page
"""
self.admin_log_in_complete()
logOut = self.browser.find_element_by_link_text('Log out')
logOut.click()
body = self.browser.find_element_by_tag_name('body')
self.assertIn('VCB Administration', body.text)
答案 0 :(得分:20)
正如我在评论中提到的,这似乎是Django中记录的错误。 Here和here是官方错误报告。如第二个链接中所述,一种解决方法是在django.contrib.auth
中交换django.contrib.contenttypes
和INSTALLED_APPS
的顺序,如下所示:
原来是什么:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'testapp'
)
应该成为:
INSTALLED_APPS = (
'django.contrib.contenttypes',
'django.contrib.auth',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'testapp'
)