Django里的单元测试

何为单元测试

单元测试是用来对一个模块、一个函数、一个接口或者一个类来进行正确性检验的自动测试工作。
比如对于函数max(a,b),我们可以编写如下的测试用例:

  1. 输入a=5,b=10,期待返回b;
  2. 输入a=10,b=5,期待返回a;
  3. 输入a=-5,b=0,期待返回b;
  4. 输入a=b,期待返回a或b;
  5. 输入非数值类型,期待抛出TypeError。

把上述测试用例放在一个测试模块中,就是一个小型但完整的单元测试。把上述测试用例放在一个测试模块中,就是一个小型但完整的单元测试。
如果单元测试通过,说明被测函数能正常工作;若不通过,要么函数有bug,要么测试条件不正确,总之,需要进行修复。

Django.test

在Django项目中,同样支持单元测试,我们需要从Django.test导入TestCase模块,针对web接口测试,我们还需要导入Client模块。

  1. 我们需要编写一个单元测试类,继承testCase模块
  2. 以test开头的方法就是测试方法,对每一类测试都需要编写一个test_xxx()方法
  3. assertEqual 判断是否相等 类似的还有大于小于什么的
  4. assertGreater 是判断a>b的一种方法
  5. assertDictContainsSubset 是判断b是否为期望值a
  6. setUp()tearDown()方法。这两个方法会分别在每调用一个测试方法的前后分别被执行,可用于初始化和虚构操作。
  7. 运行测试:python manage.py test

单元测试样例

// An highlighted block
# Create your tests here.
#登录
class adminLoginTest(TestCase):
    #初始化
    def setUp(self):
        User.objects.create_superuser('superuser', 'superuser@test.com', '123456test')
        User.objects.create_user('user', 'user@test.com', '123456test')

    #路由测试
    def test_login_url(self):
        c = Client()
        response = c.post('/api/a/login', {"username": "superuser", "password": "123456test"})
        self.assertEqual(response.status_code, 200)
    
    #superuser登录测试
    def test_superuser(self):
        c = Client()
        response = c.post('/api/a/login', {"username": "superuser", "password": "123456test"})
        self.assertEqual(json.loads(response.content.decode())['code'], 0)

    #user登录测试
    def test_user(self):
        c = Client()
        response = c.post('/api/a/login', {"username": "user", "password": "123456test"})
        self.assertEqual(json.loads(response.content.decode())['code'], 0)

    #密码错误测试
    def test_pwd_error(self):
        a_login = adminLogin()
        a_login.input = {
            'username':'superuser',
            'password':'test123456'
        }
        self.assertRaises(ValidateError, a_login.post)

    #用户名无效测试
    def test_username_not_exit(self):
        a_login = adminLogin()
        a_login.input = {
            'username':'null_user',
            'password':'123456test'
        }
        self.assertRaises(ValidateError, a_login.post)

#登出
class adminLogoutTest(TestCase):
    #登出测试
    def logoutTest(self):
        c = Client()
        response = c.post('/api/a/logout', {})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content.decode())['code'], 0)

#活动列表
class activityListTest(TestCase):
    #初始化
    def setUp(self):
        Activity.objects.create(id=1, name='act_deleted', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_DELETED, remain_tickets=1000)
        Activity.objects.create(id=2, name='act_saved', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_SAVED, remain_tickets=1000)
        Activity.objects.create(id=3, name='act_published', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_PUBLISHED, remain_tickets=1000)
    
    #get测试
    def test_get_act_List(self):
        A = activityList()
        get = A.get()
        self.assertEqual(len(get), 2)
    
    #回退
    def tearDown(self):
        Activity.objects.all().delete()

#创建活动
class create_act_Test(TestCase):
    #post测试
    def test_create_act(self):
        act = {"name": "name", "key": "key", "place": "place", "description": "description", "picUrl": "picUrl",
                     "startTime": timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), 
                     "endTime": timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)),
                     "bookStart": timezone.now(), "bookEnd": timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)), 
                     "totalTickets": 1000, "status": Activity.STATUS_PUBLISHED}
        A = activityCreate()
        A.input = act
        A.post()
        self.assertEqual(Activity.objects.get(name='name').place, "place")

    #回退
    def clear(self):
        Activity.objects.all().delete()

#删除活动
class delete_act_Test(TestCase):
    #初始化
    def setUp(self):
        Activity.objects.create(id=1, name='act_deleted', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_DELETED, remain_tickets=1000)
        Activity.objects.create(id=2, name='act_saved', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_SAVED, remain_tickets=1000)
        Activity.objects.create(id=3, name='act_published', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_PUBLISHED, remain_tickets=1000)

    #post测试
    #删除存在的活动
    def test_delete_act_exited(self):
        A_delete = activityDelete()
        A_delete.input = {'id': 2}
        A_delete.post()
        self.assertEqual(Activity.objects.get(id=2).status, Activity.STATUS_DELETED)
    #删除已删除的活动
    def test_delete_act_deleted(self):
        A_delete = activityDelete()
        A_delete.input = {'id': 1}    
        self.assertRaises(ValidateError, A_delete.post)
    #删除不存在的活动
    def test_delete_act_not_exited(self):
        A_delete = activityDelete()
        A_delete.input = {'id': 4}    
        self.assertRaises(ValidateError, A_delete.post)
    
    #回退
    def tearDown(self):
        Activity.objects.all().delete()

#活动详情
class act_details_Test(TestCase):
    #初始化
    def setUp(self):
        Activity.objects.create(id=1, name='act_saved', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_SAVED, remain_tickets=1000)
    
    #获取存在的活动
    def test_get_details_act_exited(self):
        act_detail = activityDetail()
        act_detail.input = {'id': 1}
        self.assertEqual(act_detail.get()['name'], "act_saved")

    #获取不存在的活动
    def test_get_details_act_not_exited(self):
        act_detail = activityDetail()
        act_detail.input = {'id': 2}
        self.assertRaises(ValidateError, act_detail.get)

    #回退
    def tearDown(self):
        Activity.objects.all().delete()

#微信菜单调整
class act_Menu_Test(TestCase):
    #初始化
    def setUp(self):
        Activity.objects.create(id=1, name='act_deleted', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_DELETED, remain_tickets=1000)
        Activity.objects.create(id=2, name='act_saved', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_SAVED, remain_tickets=1000)
        Activity.objects.create(id=3, name='act_published', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_PUBLISHED, remain_tickets=1000)

    #获取菜单测试
    # def test_get_menu_test(self):
    #     menu = activityMenu()
    #     act_list = menu.get()
    #     self.assertEqual(len(act_list), 1)
    #     self.assertEqual(act_list[0]['name'], 'act_published')

    #修改菜单测试
    def test_post_menu_test(self):
        menu = activityMenu()
        menu.input = {'id':2}
        self.assertRaises(ValidateError, menu.post)
    
    #回退
    def tearDown(self):
        Activity.objects.all().delete()

#检票
class activity_checkin_Test(TestCase):
    #初始化
    def setUp(self):
        act = Activity.objects.create(id=1, name='act_published', key='key', place='place',
                                description='description', start_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 8, 0, 0, 0)), pic_url="url",
                                end_time=timezone.make_aware(datetime.datetime(2018, 10, 28, 18, 0, 0, 0)), book_start=timezone.now(), book_end=timezone.make_aware(datetime.datetime(2018, 10, 27, 18, 0, 0, 0)),
                                total_tickets=1000, status=Activity.STATUS_PUBLISHED, remain_tickets=1000)
        Ticket.objects.create(student_id = '1', unique_id='1', activity= act, status=Ticket.STATUS_CANCELLED)
        Ticket.objects.create(student_id = '2', unique_id='2', activity= act, status=Ticket.STATUS_USED)
        Ticket.objects.create(student_id = '3', unique_id='3', activity= act, status=Ticket.STATUS_VALID)

    #正常检票
    def test_checkin_vaild1(self):
        C = activityCheckin()
        C.input = {'actId':1, 'studentId':'3'}
        info = C.post()
        self.assertEqual(info['ticket'], '3')

    def test_checkin_vaild2(self):
        C = activityCheckin()
        C.input = {'actId':1, 'ticket':'3'}
        info = C.post()
        self.assertEqual(info['ticket'], '3')

    #已用票检票
    def test_checkin_used1(self):
        C = activityCheckin()
        C.input = {'actId':1, 'studentId':'2'}
        self.assertRaises(ValidateError, C.post)

    def test_checkin_used2(self):
        C = activityCheckin()
        C.input = {'actId':1, 'ticket':'2'}
        self.assertRaises(ValidateError, C.post)

    #退票检票
    def test_checkin_invaild1(self):
        C = activityCheckin()
        C.input = {'actId':1, 'studentId':'1'}
        self.assertRaises(ValidateError, C.post)

    def test_checkin_invaild2(self):
        C = activityCheckin()
        C.input = {'actId':1, 'ticket':'1'}
        self.assertRaises(ValidateError, C.post)

    #回退
    def tearDown(self):
        Ticket.objects.all().delete()
        Activity.objects.all().delete()

参考文献

单元测试-廖雪峰
Django单元测试基础知识
单元测试是什么,有什么好处
Django 单元测试-自强学堂

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值