Skip to content
This repository has been archived by the owner on Jun 29, 2020. It is now read-only.

Use mysqlclient-python #1126

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ matrix:
before_install:
- ./utils/decrypt-files $password_for_secret_files
- git submodule update --init --recursive
- mv config/ci_settings.py src/kawaz/local_settings.py
- mysql -uroot -e "create database kawaz_travis"
- mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
install:
- pip install tox
- pip install coverage coveralls
Expand Down
16 changes: 16 additions & 0 deletions config/ci_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# テスト用データーベースの設定
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'kawaz_travis',
'USER': 'root',
'PASSWORD': '',
'HOST': 'localhost',
'PORT': '',
'OPTIONS': {
'connect_timeout': 60,
'init_command' : 'SET foreign_key_checks = 0;SET time_zone = "+00:00"',
},
'STORAGE_ENGINE': 'INNODB',
},
}
4 changes: 2 additions & 2 deletions config/requirements-production.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
PyMySQL<0.7.0
mysqlclient
gunicorn
git+https://github.com/kawazrepos/pylibmc.git@master#egg=pylibmc
pylibmc
1 change: 1 addition & 0 deletions config/requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
factory_boy>=2.7
coverage
faker
mysqlclient
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これは travis の事情(ローカルでは依然 sqlite を使う)なので travis.yml でインスコするべきかな

6 changes: 3 additions & 3 deletions config/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ deps=
commands=
{envbindir}/python manage.py init_database --noinput --no-fetch-entries
{envbindir}/python manage.py compilemessages
{envbindir}/python manage.py test activities -v 2
{envbindir}/python manage.py test google_calendar -v 2
{envbindir}/python manage.py test --noinput activities -v 2
{envbindir}/python manage.py test --noinput google_calendar -v 2
{envbindir}/coverage run \
--source=src/kawaz --rcfile=config/coveragerc \
manage.py test kawaz -v 2 []
manage.py test kawaz --noinput -v 2 []
{envbindir}/coverage report
{envbindir}/pip freeze

11 changes: 0 additions & 11 deletions src/kawaz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,2 @@
#! -*- coding: utf-8 -*-
#
#
#

__version__ = (0, 1, 0)
VERSION = ".".join(map(str, __version__))

try:
import pymysql
pymysql.install_as_MySQLdb()
except:
pass
4 changes: 2 additions & 2 deletions src/kawaz/apps/announcements/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ def test_published_by_authorized(self):
user = PersonaFactory()
qs = Announcement.objects.published(user)
self.assertEqual(qs.count(), 2)
self.assertEqual(qs[0], b)
self.assertEqual(qs[1], a)
self.assertIn(b, qs)
self.assertIn(a, qs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] ん、ここ出現順番のテスト崩してもいいの?出現順番を保証するようにするほうが妥当じゃない?


def test_published_by_anonymous(self):
"""
Expand Down
97 changes: 50 additions & 47 deletions src/kawaz/apps/announcements/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,11 @@ def test_staff_user_can_create_via_create_view(self):
'body' : 'サードインパクトだ!',
'silently' : True
})
self.assertRedirects(r, '/announcements/1/')
announcement = Announcement.objects.last()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

全体的に last 使ってるけど first のほうがベターかな

self.assertEqual(Announcement.objects.count(), 1) が通ることからも分かる通り MySQL で落ちたのはデータが残っていたからではなく MySQL の pk の適用方法が異なるためだと思う(たぶんシーケンシャル pk じゃないんだと邪推)なので last でも first でも返ってくるものは同じだけど、仮にゴミデータが残っていた + count() をチェックしていない を満たすテストがあった場合

  • last を使った場合:最後に追加されたものが返るのでテストが通る
  • first を使った場合:最初に追加されたものが返るのでテストが落ちる

って違いが発生してミスに気が付きやすくなると思う。

self.assertRedirects(r, '/announcements/{}/'.format(announcement.pk))
self.assertEqual(Announcement.objects.count(), 1)
e = Announcement.objects.get(pk=1)
self.assertEqual(e.title, '【悲報】データ消えました')
announcement = Announcement.objects.last()
self.assertEqual(announcement.title, '【悲報】データ消えました')
self.assertTrue('messages' in r.cookies, "No messages are appeared")

def test_authorized_user_can_create_via_create_view(self):
Expand All @@ -217,11 +218,12 @@ def test_set_last_modifier_user(self):
'body' : 'サードインパクトだ!',
'silently' : True
})
self.assertRedirects(r, '/announcements/1/')
announcement = Announcement.objects.last()
self.assertRedirects(r, '/announcements/{}/'.format(announcement.pk))
self.assertEqual(Announcement.objects.count(), 1)
e = Announcement.objects.get(pk=1)
self.assertEqual(e.author, self.nerv)
self.assertEqual(e.last_modifier, self.nerv)
announcement = Announcement.objects.last()
self.assertEqual(announcement.author, self.nerv)
self.assertEqual(announcement.last_modifier, self.nerv)

def test_staffs_cannot_modify_author_id(self):
'''
Expand All @@ -239,11 +241,12 @@ def test_staffs_cannot_modify_author_id(self):
'silently' : True,
'author' : other.pk
})
self.assertRedirects(r, '/announcements/1/')
announcement = Announcement.objects.last()
self.assertRedirects(r, '/announcements/{}/'.format(announcement.pk))
self.assertEqual(Announcement.objects.count(), 1)
e = Announcement.objects.get(pk=1)
self.assertEqual(e.author, self.nerv)
self.assertNotEqual(e.author, other)
announcement = Announcement.objects.last()
self.assertEqual(announcement.author, self.nerv)
self.assertNotEqual(announcement.author, other)
self.assertTrue('messages' in r.cookies, "No messages are appeared")


Expand All @@ -265,29 +268,29 @@ def setUp(self):

def test_anonymous_user_can_not_view_announcement_update_view(self):
'''Tests anonymous user can not view AnnouncementUpdateView'''
r = self.client.get('/announcements/1/update/')
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/1/update/')
r = self.client.get('/announcements/{}/update/'.format(self.announcement.pk))
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/{}/update/'.format(self.announcement.pk))

def test_wille_user_can_not_view_announcement_update_view(self):
'''Tests wille user can not view AnnouncementUpdateView'''
self.assertTrue(self.client.login(username=self.wille, password='password'))
r = self.client.get('/announcements/1/update/')
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/1/update/')
r = self.client.get('/announcements/{}/update/'.format(self.announcement.pk))
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/{}/update/'.format(self.announcement.pk))

def test_general_user_can_not_view_announcement_update_view(self):
'''
Tests general user can view AnnouncementUpdateView
'''
self.assertTrue(self.client.login(username=self.other, password='password'))
r = self.client.get('/announcements/1/update/')
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/1/update/')
r = self.client.get('/announcements/{}/update/'.format(self.announcement.pk))
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/{}/update/'.format(self.announcement.pk))

def test_staff_can_view_announcement_update_view(self):
'''
Tests staff members can view AnnouncementUpdateView
'''
self.assertTrue(self.client.login(username=self.nerv, password='password'))
r = self.client.get('/announcements/1/update/')
r = self.client.get('/announcements/{}/update/'.format(self.announcement.pk))
self.assertTemplateUsed(r, 'announcements/announcement_form.html')
self.assertTrue('object' in r.context_data)
self.assertEqual(r.context_data['object'], self.announcement)
Expand All @@ -297,13 +300,13 @@ def test_anonymous_user_can_not_update_via_update_view(self):
Tests anonymous user can not update announcement via AnnouncementUpdateView
It will redirect to LOGIN_URL
'''
r = self.client.post('/announcements/1/update/', {
r = self.client.post('/announcements/{}/update/'.format(self.announcement.pk), {
'pub_state' : 'public',
'title' : '【悲報】データ消えました',
'body' : 'サードインパクトだ!',
'silently' : True,
})
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/1/update/')
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/{}/update/'.format(self.announcement.pk))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

どのみち format() 使うなら '{}?next=...{}/update/'.format(settings.LOGIN...) にしたほうがいいかな

self.assertEqual(self.announcement.title, 'かわずたんのお知らせだよ☆')

def test_wille_user_can_not_update_via_update_view(self):
Expand All @@ -312,13 +315,13 @@ def test_wille_user_can_not_update_via_update_view(self):
It will redirect to LOGIN_URL
'''
self.assertTrue(self.client.login(username=self.wille, password='password'))
r = self.client.post('/announcements/1/update/', {
r = self.client.post('/announcements/{}/update/'.format(self.announcement.pk), {
'pub_state' : 'public',
'title' : '【悲報】データ消えました',
'body' : 'サードインパクトだ!',
'silently' : True,
})
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/1/update/')
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/{}/update/'.format(self.announcement.pk))
self.assertEqual(self.announcement.title, 'かわずたんのお知らせだよ☆')

def test_other_user_cannot_update_via_update_view(self):
Expand All @@ -327,28 +330,28 @@ def test_other_user_cannot_update_via_update_view(self):
It will redirect to LOGIN_URL
'''
self.assertTrue(self.client.login(username=self.other, password='password'))
r = self.client.post('/announcements/1/update/', {
r = self.client.post('/announcements/{}/update/'.format(self.announcement.pk), {
'pub_state' : 'public',
'title' : '【悲報】データ消えました',
'body' : 'サードインパクトだ!',
'silently' : True,
})
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/1/update/')
self.assertRedirects(r, settings.LOGIN_URL + '?next=/announcements/{}/update/'.format(self.announcement.pk))
self.assertEqual(self.announcement.title, 'かわずたんのお知らせだよ☆')

def test_staff_can_update_via_update_view(self):
'''Tests author user can update announcement via AnnouncementUpdateView'''
self.assertTrue(self.client.login(username=self.nerv, password='password'))
r = self.client.post('/announcements/1/update/', {
r = self.client.post('/announcements/{}/update/'.format(self.announcement.pk), {
'pub_state' : 'public',
'title' : '【悲報】データ消えました',
'body' : 'サードインパクトだ!',
'silently' : True,
})
self.assertRedirects(r, '/announcements/1/')
self.assertRedirects(r, '/announcements/{}/'.format(self.announcement.pk))
self.assertEqual(Announcement.objects.count(), 1)
e = Announcement.objects.get(pk=1)
self.assertEqual(e.title, '【悲報】データ消えました')
announcement = Announcement.objects.last()
self.assertEqual(announcement.title, '【悲報】データ消えました')
self.assertTrue('messages' in r.cookies, "No messages are appeared")

def test_set_last_modifier_via_update_view(self):
Expand All @@ -357,17 +360,17 @@ def test_set_last_modifier_via_update_view(self):
"""
previous_modifier = self.announcement.last_modifier
self.assertTrue(self.client.login(username=self.nerv, password='password'))
r = self.client.post('/announcements/1/update/', {
r = self.client.post('/announcements/{}/update/'.format(self.announcement.pk), {
'pub_state' : 'public',
'title' : '【悲報】データ消えました',
'body' : 'サードインパクトだ!',
'silently' : True,
})
self.assertRedirects(r, '/announcements/1/')
self.assertRedirects(r, '/announcements/{}/'.format(self.announcement.pk))
self.assertEqual(Announcement.objects.count(), 1)
e = Announcement.objects.get(pk=1)
self.assertEqual(e.last_modifier, self.nerv)
self.assertNotEqual(e.last_modifier, previous_modifier)
announcement = Announcement.objects.last()
self.assertEqual(announcement.last_modifier, self.nerv)
self.assertNotEqual(announcement.last_modifier, previous_modifier)

def test_user_cannot_modify_author_id(self):
'''
Expand All @@ -378,19 +381,19 @@ def test_user_cannot_modify_author_id(self):
'''
other = PersonaFactory()
self.assertTrue(self.client.login(username=self.nerv, password='password'))
r = self.client.post('/announcements/1/update/', {
r = self.client.post('/announcements/{}/update/'.format(self.announcement.pk), {
'pub_state' : 'public',
'title' : 'ID書き換えます!',
'body' : 'サードインパクトだ!',
'silently' : True,
'author' : other.pk # crackers attempt to masquerade
})
self.assertRedirects(r, '/announcements/1/')
self.assertRedirects(r, '/announcements/{}/'.format(self.announcement.pk))
self.assertEqual(Announcement.objects.count(), 1)
e = Announcement.objects.get(pk=1)
self.assertEqual(e.author, self.user)
self.assertNotEqual(e.author, other)
self.assertEqual(e.title, 'ID書き換えます!')
announcement = Announcement.objects.last()
self.assertEqual(announcement.author, self.user)
self.assertNotEqual(announcement.author, other)
self.assertEqual(announcement.title, 'ID書き換えます!')
self.assertTrue('messages' in r.cookies, "No messages are appeared")

class AnnouncementDeleteViewTestCase(TestCase):
Expand All @@ -414,7 +417,7 @@ def test_author_can_delete_via_announcement_delete_view(self):
Tests author can delete its own announcements via AnnouncementDeleteView
'''
self.assertTrue(self.client.login(username=self.user, password='password'))
r = self.client.post('/announcements/1/delete/', {})
r = self.client.post('/announcements/{}/delete/'.format(self.announcement.pk), {})
self.assertRedirects(r, '/announcements/')
self.assertEqual(Announcement.objects.count(), 0)
self.assertTrue('messages' in r.cookies, "No messages are appeared")
Expand All @@ -424,7 +427,7 @@ def test_staff_can_delete_via_announcement_delete_view(self):
Tests members can delete its announcements via AnnouncementDeleteView
'''
self.assertTrue(self.client.login(username=self.nerv, password='password'))
r = self.client.post('/announcements/1/delete/', {})
r = self.client.post('/announcements/{}/delete/'.format(self.announcement.pk), {})
self.assertRedirects(r, '/announcements/')
self.assertEqual(Announcement.objects.count(), 0)
self.assertTrue('messages' in r.cookies, "No messages are appeared")
Expand All @@ -434,26 +437,26 @@ def test_other_cannot_delete_via_announcement_delete_view(self):
Tests others cannot delete announcements via AnnouncementDeleteView
'''
self.assertTrue(self.client.login(username=self.other, password='password'))
r = self.client.post('/announcements/1/delete/', {})
r = self.client.post('/announcements/{}/delete/'.format(self.announcement.pk), {})
self.assertEqual(Announcement.objects.count(), 1)
self.assertRedirects(r, '{0}?next=/announcements/1/delete/'.format(settings.LOGIN_URL))
self.assertRedirects(r, '{0}?next=/announcements/{1}/delete/'.format(settings.LOGIN_URL, self.announcement.pk))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nil: 順番通り適用するなら {} を連続して使えば OK


def test_wille_cannot_delete_via_announcement_delete_view(self):
'''
Tests wille cannot delete announcements via AnnouncementDeleteView
'''
self.assertTrue(self.client.login(username=self.wille, password='password'))
r = self.client.post('/announcements/1/delete/', {})
r = self.client.post('/announcements/{}/delete/'.format(self.announcement.pk), {})
self.assertEqual(Announcement.objects.count(), 1)
self.assertRedirects(r, '{0}?next=/announcements/1/delete/'.format(settings.LOGIN_URL))
self.assertRedirects(r, '{0}?next=/announcements/{1}/delete/'.format(settings.LOGIN_URL, self.announcement.pk))

def test_anonymous_cannot_delete_via_announcement_delete_view(self):
'''
Tests anonymous cannot delete announcements via AnnouncementDeleteView
'''
r = self.client.post('/announcements/1/delete/', {})
r = self.client.post('/announcements/{}/delete/'.format(self.announcement.pk), {})
self.assertEqual(Announcement.objects.count(), 1)
self.assertRedirects(r, '{0}?next=/announcements/1/delete/'.format(settings.LOGIN_URL))
self.assertRedirects(r, '{0}?next=/announcements/{1}/delete/'.format(settings.LOGIN_URL, self.announcement.pk))


class AnnouncementListViewTestCase(TestCase):
Expand Down
8 changes: 4 additions & 4 deletions src/kawaz/apps/blogs/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ def test_published_with_authenticated(self):
user = PersonaFactory()
qs = Entry.objects.published(user)
self.assertEqual(qs.count(), 2)
self.assertEqual(qs[0], self.entries[1])
self.assertEqual(qs[1], self.entries[0])
self.assertIn(self.entries[0], qs)
self.assertIn(self.entries[1], qs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ここも順番保証した方がいいと思う。MySQL で落ちるのであれば MySQL が返す順番がおかしいはず


def test_published_with_wille(self):
'''Tests Entry.objects.published() with wille user returns only public entries '''
Expand Down Expand Up @@ -132,15 +132,15 @@ def test_get_absolute_url(self):
user = PersonaFactory(username='mecha_kawaztan')
published_at = datetime.datetime(2112, 9, 21, tzinfo=timezone.utc)
entry = EntryFactory(published_at=published_at, author=user)
self.assertEqual(entry.get_absolute_url(), '/blogs/mecha_kawaztan/2112/9/21/1/')
self.assertEqual(entry.get_absolute_url(), '/blogs/mecha_kawaztan/2112/9/21/{}/'.format(entry.pk))

def test_get_absolute_url_of_draft(self):
'''
Tests get_absolute_url of draft returns update page.
'''
user = PersonaFactory(username='kawaztan_kawaztan')
entry = EntryFactory(pub_state='draft', author=user)
self.assertEqual(entry.get_absolute_url(), '/blogs/kawaztan_kawaztan/1/update/')
self.assertEqual(entry.get_absolute_url(), '/blogs/kawaztan_kawaztan/{}/update/'.format(entry.pk))

def test_published_at_date_property(self):
'''
Expand Down
Loading