From 8e5e788bcdc6fa85ba89ac2bbd425140299c0b9d Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 23 Aug 2016 00:39:07 +0800 Subject: [PATCH] Test case added --- apps/users/forms.py | 3 +- apps/users/models.py | 17 ++++- apps/users/templates/users/_user.html | 3 +- apps/users/tests.py | 103 ++++++++++++++++++-------- apps/users/views.py | 4 + 5 files changed, 94 insertions(+), 36 deletions(-) diff --git a/apps/users/forms.py b/apps/users/forms.py index 47ca32653..cbd459060 100644 --- a/apps/users/forms.py +++ b/apps/users/forms.py @@ -29,13 +29,12 @@ class UserUpdateForm(ModelForm): class Meta: model = User fields = [ - 'name', 'email', 'groups', 'wechat', 'avatar', + 'name', 'email', 'groups', 'wechat', 'phone', 'enable_otp', 'role', 'date_expired', 'comment', ] help_texts = { 'username': '* required', - 'name': '* required', 'email': '* required', 'groups': '* required' } diff --git a/apps/users/models.py b/apps/users/models.py index f5fc7b7ec..46ffefcdb 100644 --- a/apps/users/models.py +++ b/apps/users/models.py @@ -7,6 +7,7 @@ from django.contrib.auth.hashers import make_password from django.utils import timezone from django.db import models from django.contrib.auth.models import AbstractUser, Permission +from django.db import OperationalError class Role(models.Model): @@ -23,6 +24,12 @@ class Role(models.Model): def __unicode__(self): return self.name + def delete(self, using=None, keep_parents=False): + if self.user_set.all().count() > 0: + raise OperationalError('Role %s has some member, should not be delete.' % self.name) + else: + return super(Role, self).delete(using=using, keep_parents=keep_parents) + class Meta: db_table = 'role' @@ -56,7 +63,7 @@ class UserGroup(models.Model): @classmethod def initial(cls): - group_or_create = cls.objects.get_or_create(name='All', comment='Default user group for all user', + group_or_create = cls.objects.get_or_create(name='Default', comment='Default user group for all user', created_by='System') return group_or_create[0] @@ -93,7 +100,7 @@ class User(AbstractUser): phone = models.CharField(max_length=20, blank=True, verbose_name='手机号') enable_otp = models.BooleanField(default=False, verbose_name='启用二次验证') secret_key_otp = models.CharField(max_length=16, blank=True) - role = models.ForeignKey(Role, on_delete=models.PROTECT, verbose_name='角色') + role = models.ForeignKey(Role, on_delete=models.SET('None'), verbose_name='角色') private_key = models.CharField(max_length=5000, blank=True, verbose_name='ssh私钥') # ssh key max length 4096 bit public_key = models.CharField(max_length=1000, blank=True, verbose_name='公钥') comment = models.TextField(max_length=200, blank=True, verbose_name='描述') @@ -124,10 +131,12 @@ class User(AbstractUser): if not self.name: self.name = self.username super(User, self).save(args, **kwargs) - # Set user default group 'All' + # Todo: It's have bug group = UserGroup.initial() - self.groups.add(group) + if group not in self.groups.all(): + self.groups.add(group) + super(User, self).save(args, **kwargs) class Meta: db_table = 'user' diff --git a/apps/users/templates/users/_user.html b/apps/users/templates/users/_user.html index 88337e85b..66d350056 100644 --- a/apps/users/templates/users/_user.html +++ b/apps/users/templates/users/_user.html @@ -41,13 +41,14 @@

角色安全

{{ form.role|bootstrap_horizontal }} -
+
+ {{ form.date_expired.errors }}
diff --git a/apps/users/tests.py b/apps/users/tests.py index b3fac7c25..dd43e0616 100644 --- a/apps/users/tests.py +++ b/apps/users/tests.py @@ -4,26 +4,12 @@ from random import choice import forgery_py from django.utils import timezone +from django.shortcuts import reverse from django.test import TestCase, Client, TransactionTestCase from django.test.utils import setup_test_environment from django.db import IntegrityError, transaction from .models import User, UserGroup, Role, init_all_models - - -setup_test_environment() -client = Client() - - -def create_usergroup(name): - pass - - -def get_random_usergroup(): - pass - - -def create_user(username, name, email, groups): - pass +from django.contrib.auth.models import Permission def gen_username(): @@ -42,54 +28,113 @@ class UserModelTest(TransactionTestCase): def setUp(self): init_all_models() - def test_user_duplicate(self): - # 创建一个基准测试用户 + # 创建一个用户用于测试 role = choice(Role.objects.all()) user = User(name='test', username='test', email='test@email.org', role=role) user.save() - # 创建一个姓名一致的用户, 应该创建成功 + def test_initial(self): + self.assertEqual(User.objects.all().count(), 2) + self.assertEqual(Role.objects.all().count(), 3) + self.assertEqual(UserGroup.objects.all().count(), 1) + + @property + def role(self): + return choice(Role.objects.all()) + + # 创建一个姓名一致的用户, 应该创建成功 + def test_user_name_duplicate(self): user1 = User(name='test', username=gen_username(), password_raw=gen_username(), - email=gen_email(), role=role) + email=gen_email(), role=self.role) try: user1.save() user1.delete() except IntegrityError: self.assertTrue(0, 'Duplicate not allowed.') - # 创建一个用户名一致的用户, 应该创建不成功 - user2 = User(username='test', email=gen_email(), role=role) - + # 创建一个用户名一致的用户, 应该创建不成功 + def test_user_username_duplicate(self): + user2 = User(username='test', email=gen_email(), role=self.role) try: user2.save() self.assertTrue(0, 'Duplicate allowed.') except IntegrityError: pass - # 创建一个Email一致的用户,应该创建不成功 - user3 = User(username=gen_username(), email='test@email.org', role=role) + # 创建一个Email一致的用户,应该创建不成功 + def test_user_email_duplicate(self): + user3 = User(username=gen_username(), email='test@email.org', role=self.role) try: user3.save() self.assertTrue(0, 'Duplicate allowed.') except IntegrityError: pass + # 用户过期测试 def test_user_was_expired(self): - role = choice(Role.objects.all()) date = timezone.now() - timezone.timedelta(days=1) user = User(name=gen_name(), username=gen_username(), - email=gen_email(), role=role, date_expired=date) + email=gen_email(), role=self.role, date_expired=date) self.assertTrue(user.is_expired()) + # 测试用户默认会输入All用户组 def test_user_with_default_group(self): role = choice(Role.objects.all()) user = User(username=gen_username(), email=gen_email(), role=role) user.save() self.assertEqual(user.groups.count(), 1) - self.assertEqual(user.groups.first().name, 'All') + self.assertEqual(user.groups.first().name, 'Default') + + def test_user_password_authenticated(self): + password = gen_username() * 3 + user = User(username=gen_username(), password_raw=password, role=self.role) + user.save() + self.assertTrue(user.check_password(password)) + self.assertFalse(user.check_password(password*2)) + + def tearDown(self): + User.objects.all().delete() + UserGroup.objects.all().delete() + Role.objects.all().delete() + + +class RoleModelTestCase(TransactionTestCase): + def setUp(self): + Role.objects.all().delete() + Role.initial() + + def test_role_initial(self): + self.assertEqual(Role.objects.all().count(), 3) + + def test_create_new_role(self): + role = Role(name=gen_name(), comment=gen_name()*3) + role.save() + role.permissions = Permission.objects.all() + role.save() + + self.assertEqual(Role.objects.count(), 4) + role = Role.objects.last() + self.assertEqual(role.permissions.all().count(), Permission.objects.all().count()) + + +class UserGroupModelTestCase(TransactionTestCase): + pass class UserListViewTests(TestCase): - pass + def setUp(self): + init_all_models() + User.generate_fake() + + def test_list_view_with_one_user(self): + response = self.client.get(reverse('users:user-list')) + self.assertEqual(response.status_code, 200) + self.assertContains(response, 'Admin') + self.assertQuerysetEqual(response.context['user_list'], [repr(user) for user in User.objects.all()]) + + def test_pagination(self): + response = self.client.get(reverse('users:user-list')) + self.assertContains(response.status_code, 200) + diff --git a/apps/users/views.py b/apps/users/views.py index 66ca0294f..fb7483bdc 100644 --- a/apps/users/views.py +++ b/apps/users/views.py @@ -72,6 +72,10 @@ class UserUpdateView(UpdateView): user.set_password(password) return super(UserUpdateView, self).form_valid(form) + def form_invalid(self, form): + print(form.errors) + return super(UserUpdateView, self).form_invalid(form) + class UserDeleteView(DeleteView): model = User