Unit testing framework unittest
python unittest is carrying a unit testing framework, without having to install, easy to use.
unittest in the core part is: TestFixture, TestCase, TestSuite, TestRunner
unittest case of running processes:
- A complete written TestCase
- A plurality TestCase TestSuite TestLoder is loaded into the inside, can also be nested TestSuite TestSuite
- The results from the TextTestRunner to perform TestSuite, test saved in the TextTestResult
- TestFixture refers to the preparation and recovery environment
TestFixture
Prepare for the test environment and reducing recovery, generally used in the following several functions:
- Run before each test case run:) (setUp
- tearDown (): executed after completion of each test case run
- setUpClass (): You must use @classmethod decorator run only once before all run case
- tearDownClass (): You must use @classmethod decorator, runs only run once after the completion of all case
TestCase
- The results:
成功是 .
failure is F, the error is E, S is skipped - The order of execution of test cases with the method does not matter, in alphabetical order by default
- Each test methods are
test 开头
Test model file:
# -*- coding: utf-8 -*-
import unittest
class TestMy(unittest.TestCase):
def setUp(self):
# 每个测试用例运行之前执行
print 'setUp'
def tearDown(self):
# 每个测试用例运行之后执行
print 'tearDown'
@classmethod
def setUpClass(cls):
# 所有测试用例运行之前执行
print 'setUpClass'
@classmethod
def tearDownClass(cls):
# 所有测试用例运行之后执行
print 'tearDownClass'
def run_test(self):
# 不是以test开头,不是测试用例
print 'run'
def test_run_a(self):
# 测试用例
self.assertEqual(1, 1)
def test_run_b(self):
# 测试用例
self.assertEqual(1, 2)
After the unit tests run to completion, success will print a ".", Will show the assertion failure of local failure.
Django unit testing
django unit based on the test module is written unittest. We use class named django.test.TestCase, inherited from the python unittest.TestCase. So it's the whole process is entirely consistent with unittest.
- Different points: the Client class is defined for analog transmission request more in the test project Django.test module.
from django.test import TestCase
import json
class TestAlarm(TestCase):
def test_nic_type(self):
# 测试获取NIC类型接口
r = self.client.get('/api/home/nic_type/')
self.assertEqual(r.status_code, 200)
content = json.loads(r.content)
self.assertEqual(content['result'], True)
Django support request type
Request type | Call the method |
---|---|
Post request | post(path, data=None, content_type=MULTIPART_CONTENT, follow=False, secure=False, **extra) |
Get request | get(path, data=None, follow=False, secure=False, **extra) |
Put request | put(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra) |
Patch Request | patch(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra) |
Delete request | delete(path, data='', content_type='application/octet-stream', follow=False, secure=False, **extra) |
Common Definition:
parameter name | Meaning Explanation |
---|---|
path | Send a request using the url |
data | When a data transmission request carrying |
content_type | Carrying the format of the data |
secure | The client HTTPS request analog |
follow | The client will follow any redirects |
Wherein: post, put, patch, delete request when the application process is content_type JSON, if data is dict, list or tuple type, is required json.dumps () to serialize /.
Receiving and processing the request data
Client request issued by the object after a series of operations of the test unit, the data is returned to the return value returned in the form. In general, data is returned in the form of a rear end json格式
, after receiving the data call needs to json方法
be resolved.
import json
def test_nic_type(self):
# 测试获取NIC类型接口
response = self.client.get('/api/home/nic_type/')
self.assertEqual(response.status_code, 200)
content = json.loads(response.content)
Which, response of common attributes are:
- status_code: http status codes
- content: reponse of the body, json format, when analyzed by way json
Results show
- self.assertEqual(1, 2): 断言1==2
- self.assertTrue (isinstance (content, list)): assert that the content type is a list
- self.assertContains (response, text, count = None, status_code = 200, msg_prefix = '', html = False): whether the corresponding response to the assertion status_code text and content. True will set the html text as html treatment.
- self.assertJSONEqual (raw, expected_data, msg = None): Json fragments and asserts quite raw and expected_data.
mock data
mock auxiliary unit test module for testing is not convenient to call someone else's interface.
use:
In the python2.x, the mock is a separate module, use need to install
pip install mock
After python3.3, mock unittest been incorporated into a module, a unit testing unittest part, come directly into the line
from unittest import mock
Example of use
We need to test methods:
def get_os_account(cls, bk_biz_id):
params = {
'bk_biz_id': bk_biz_id
}
accounts = JobApi.get_os_account(params=params)
return accounts
Wherein when JobApi.get_os_account not call for the external interface unit tests, it is necessary to use mock data using the following method:
import mock
def test_get_os_account(self):
"""
测试方法get_os_account
:return:
"""
JobApi.get_os_account = mock.MagicMock(return_value=Mock_Os)
data = Rules.get_os_account(
bk_biz_id=2
)
self.assertTrue(isinstance(data, dict))
Mock_Os which is:
Mock_Os = {
"result": True,
"code": 0,
"message": "success",
"data": [
{
"id": 2,
"account": "Administrator",
"creator": "system",
"os": "Windows",
"alias": "Administrator",
"bk_biz_id": 2,
"create_time": "2018-03-22 15:36:31"
}
]
}
database
Testing is required databases, django will generate a separate database for testing. Regardless of whether your tests passed, after all when you perform the test, the test database is destroyed.
- Points to note: during the execution of unit tests, Django will generate a temporary database, so users need to have a connection to the database to create and delete rights to the database.
- By default, the name of the test database is test_DATABASE_NAME, DATABASE_NAME is the name of the database you configured in settings.py years;
- If you need to test a database other names can be specified TEST_DATABASE_NAME values in settings.py
Configure the test database, increase TEST field in setting.py file DATABASES
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 默认用mysql
'NAME': 'hn_collector', # 数据库名 (默认与APP_ID相同)
'USER': 'root', # 你的数据库user
'PASSWORD': '123456', # 你的数据库password
'HOST': '127.0.0.1', # 开发的时候,使用localhost
'PORT': '3306', # 默认3306
'TEST': {
'NAME': 'data_collector_test',
'CHARSET': 'utf8',
'COLLATION': 'utf8_general_ci'
},
'OPTIONS': {'charset': 'utf8'},
},
}
Recommended configuration database, you can modify the configuration of the test database. Otherwise it will be easier to go wrong: encoding issues such as: Chinese can not be put in storage, etc.
keepdb
When writing unit tests, each time re-create the MySQL database tables takes a long time, so in the case of the results of the same table, want to use the parameter keepdb
python manage.py test --keepdb
Test Data: fixtures
Some projects are based on database development, if the database has no data, then for a database-based web sites, test case not much use. In order to join the test data to the test database is more convenient, django provides load fixtures Methods.
fixture is a series of data sets, django know how to import it into the database.
Steps for usage
- Fixtures create a folder in myapp, create a file in the folder myapp.json
- Json configuration file
[{
"fields": {
"subnets": "1",
"update_time": "2020-03-13T16:48:15",
"name": "test",
"ch_operator": null,
"scan_time": "2020-03-13T18:31:30",
"edit_user": null,
"is_delete": 0,
"create_user": "wangying",
"create_time": "2020-03-13T16:48:15"
},
"model": "tasks.tasksconfig",
"pk": 3
}, {
"fields": {
"status": 1,
"edit_time": "2020-03-13T16:48:15",
"is_delete": 0,
"create_user": "wangying",
"create_time": "2020-03-13T16:48:15",
"frequency": 60,
"time": "02:00:00",
"day": 5,
"tasksconfig": 3
},
"model": "tasks.cycle",
"pk": 3
}]
- If there is actual data in the database, the data may be copied directly to the myapp.json file copy command follows
python manage.py dumpdata myapp >myapp/fixtures/myapp.json
- setting.py added: FIXTURE_DIRS = ( '/ path / to / api / fixtures /',)
- Use the test file:
class TestHome(BaseTestCase):
fixtures = ['ip_address.json']
def setUp(self):
super(TestHome, self).setUp()
Login authentication
Directly to the login authentication mock out, the middleware can bypass authentication (not recommended)
@patch('account.middlewares.LoginMiddleware',return_value={'user': 'wy'})
def test_all_sub(self, user):
Direct cookie assignment
def setUp(self):
self.client.cookies['bk_token'] = 'bk_token'
Celery unit testing
Unit testing asynchronous tasks
A simple example:
@task()
def add():
print '33333'
def task_celery(self, request):
type = request.GET.get('type')
if int(type) == 1:
add.delay()
data = {
'status': 1
}
else:
data = {
'status': 2
}
return Response(data)
Unit Test Method: Use CELERY_ALWAYS_EAGER = True
- Decorator override_settings
from django.test.utils import override_settings
@override_settings(CELERY_ALWAYS_EAGER=True)
def test_add(self):
param = {
'type': 1
}
r = self.client.get('/api/task/task_celery/', param, content_type='application/json')
self.assertEqual(r.status_code, 200)
content = json.loads(r.content)
self.assertEqual(content['result'], True)
- Directly modify settings
from django.conf import settings
def setUp(self):
settings.CELERY_ALWAYS_EAGER = True
If set CELERY_ALWAYS_EAGER=True
, the following two lines of code no difference
add.delay()
add()
File Upload:
Simply provide the file name as the key field, and provide a file to upload a file handle as the value.
def test_upload_file(self):
"""
测试方法 upload_file
:return:
"""
with open('apps/test_handlers/mock_data/upload_file/ydauto_tomcat.zip') as fb:
r = self.client.post('/api/scripts/', data={'file': fb})
content = json.loads(r.content)
self.assertEqual(r.status_code, 200)
file is just a key, you can define your own
Running unit tests
- Test the entire project
python manage.py test
- Testing an application
python manage.py test app_name
- Test only a Case
python manage.py test MyTestCase
- Only one test method
python manage.py test test_func
Test by: