Я пытаюсь запустить функциональные тесты, используя Selenium для проекта Django. Как в Firefox, так и в Chrome я получаю странную ошибку внешнего ключа, когда я пытаюсь проверить, что суперпользователь может изменить статус обычного пользователя для персонала (я предполагаю, что все это проверено с помощью внутреннего тестирования Django, но подумал, что было бы хорошей практикой включить это в тестировании моего приложения, поскольку мои пользовательские сценарии зависят от функциональности). Похоже, что Django не любит, что Selenium ничего не сохраняет в базе данных? Эта одна ошибка также просачивается в мои другие тесты, поэтому кажется, что что-то ломается за кулисами - например, Selenium теряет соединение с базой данных. Кто-нибудь знает, почему это произошло?? Я готов свалить тест в пользу того, что функция работает, но хотелось бы исправить это и использовать тест.Selenium/Django дает ошибку внешнего ключа
Один из возможных симптомов заключается в том, что в Chrome между выводами «отмечен флажок» и «нажата кнопка сохранения», я получаю сломанную трубку (в Firefox не работает).
Кажется ломаться здесь, когда Селен нажимает на кнопку 'Сохранить':
# 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 "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/test/testcases.py", line 268, in __call__
self._post_teardown()
File "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/test/testcases.py", line 533, in _post_teardown
self._fixture_teardown()
File "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/test/testcases.py", line 553, in _fixture_teardown
skip_validation=True, reset_sequences=False)
File "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/__init__.py", line 161, in call_command
return klass.execute(*args, **defaults)
File "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/base.py", line 255, in execute
output = self.handle(*args, **options)
File "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/core/management/base.py", line 385, in handle
return self.handle_noargs(**options)
File "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/dispatch/dispatcher.py", line 170, in send
response = receiver(signal=self, sender=sender, **named)
File "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/models/query.py", line 902, in _batched_insert
using=self.db)
File "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/virtual_environments/VideoSearch/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 937, in execute_sql
cursor.execute(sql, params)
File "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/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 "/Users/cjshaw/Documents/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`))')
===== Изменено с кодом
- Также обратите внимание, что test_admin_can_make_a_user_staff вызывает другие мои тесты с ошибкой с тем же адресом ror - но они в порядке, когда я вынимаю команду «save» из этого теста.
- Я предполагаю, что две вещи, которые я действительно не понимаю, это: 1) Почему это происходит со встроенным администраторским представлением Django (подумал, что это должно сработать) и 2) Почему одна тестовая ошибка каскадируется до моих других тестов? Я думал, что они независимы.
Спасибо, что посмотрели на это!
С моего 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='[email protected]')
User.objects.create_user(username='teaching',
password='assistant',
email='[email protected]')
# 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)
I предположил бы, потому что он пытается сохранить FK, которого не существует. Вероятно, вы хотите заполнить тестовый db приборами. –
Извините, не могли бы вы быть более конкретными? Я изучаю его больше сейчас, но похоже, что он должен быть таким же, как предварительная заполнение базы данных, что я делаю в своем setUp(). Я бы подумал, что существуют FK, поскольку пользователь уже существует? -Благодаря! – user
показать нам свой код. –