Panduan gaya pengujian Python saya

Pada artikel ini, saya mencoba mengumpulkan beberapa teknik pengujian Python saya. Anda tidak boleh menganggapnya sebagai dogma, karena saya pikir seiring waktu saya akan memperbarui praktik saya.





Sedikit terminologi

  • The Target adalah apa yang Anda saat ini sedang menguji. Mungkin itu adalah fungsi, metode, atau perilaku yang dihasilkan oleh sekumpulan elemen.





  • โ€“ , . , ( , ), โ€“ , , .





  • - . -. . , .





  • โ€“ , . -, ยซยป .





,

pytest. , . , transport.py test_transport.py.





, .





def refresh(...):
    ...

def test_refresh():
    ...
      
      



, , , :





def test_refresh_failure():
    ...

def test_refresh_with_timeout():
    ...
      
      



, , , , . , :





class Thing(object):
   ...

class TestThing(object):
    def test_something(self):
       ...
      
      



test_constructor



, , test_default_state







def test_default_state(self):
    credentials = self.make_credentials()
    # No access token, so these shouldn't be valid.
    assert not credentials.valid
    # Expiration hasn't been set yet
    assert not credentials.expired
    # Scopes aren't required for these credentials
    assert not credentials.requires_scopes
      
      



assert , ,

, . , : ( ) . . . , , . , .





, , , :





test_payload = {'test': 'value'}
encoded = jwt.encode(signer, test_payload)
expected_header = {'typ': 'JWT', 'alg': 'RS256', 'kid': signer.key_id}
expected_call = json.dumps(expected_header) + '.' + json.dumps(test_payload)
signer.sign.assert_called_once_with(expected_call)
      
      



, , , :





test_payload = {'test': 'value'}
encoded = jwt.encode(signer, test_payload)
header, payload, _, _ = jwt._unverified_decode(encoded)
assert payload == test_payload
assert header == {'typ': 'JWT', 'alg': 'RS256', 'kid': signer.key_id}
      
      



, assert_call



*, , , . , , , , , , . , ( ).





,

, - , , . , , .





, ( ):





signer = mock.create_autospec(crypt.Signer, instance=True)
signer.key_id = 1

test_payload = {'test': 'value'}
encoded = jwt.encode(signer, test_payload)

expected_header = {'typ': 'JWT', 'alg': 'RS256', 'kid': signer.key_id}
expected_call = json.dumps(expected_header) + '.' + json.dumps(test_payload)
signer.sign.assert_called_once_with(expected_call)
      
      



- , , :





signer = crypt.RSASigner.from_string(PRIVATE_KEY_BYTES, '1')
test_payload = {'test': 'value'}
encoded = jwt.encode(signer, test_payload)
header, payload, _, _ = jwt._unverified_decode(encoded)
assert payload == test_payload
assert header == {'typ': 'JWT', 'alg': 'RS256', 'kid': signer.key_id}
      
      



, , , , .





 

, Mock- . mock.create_autospec()



(https://docs.python.org/3/library/unittest.mock.html#unittest.mock.create_autospec) mock.patch(autospec=True)



(https://docs.python.org/3/library/unittest.mock.html#autospeccing), . , , , . , , , , , !





, , , :





signer = mock.Mock()

encoded = jwt.encode(signer, test_payload)
...
signer.sign.assert_called_once_with(expected_call)
      
      



, , . , , :





signer = mock.Mock(spec=['sign', 'key_id'])

encoded = jwt.encode(signer, test_payload)
...
signer.sign.assert_called_once_with(expected_call)
      
      



โ€“ mock.create_autospec()



mock.patch(..., autospec=True)



. , . , , :





signer = mock.create_autospec(crypt.Signer, instance=True)

encoded = jwt.encode(signer, test_payload)
...
signer.sign.assert_called_once_with(expected_call)
      
      



autospec, , , . , .





, , , , , , , (stub). , -, , , (, in-memory ).





, :





class CredentialsStub(google.auth.credentials.Credentials):
    def __init__(self, token='token'):
        super(CredentialsStub, self).__init__()
        self.token = token

    def apply(self, headers, token=None):
        headers['authorization'] = self.token

    def before_request(self, request, method, url, headers):
        self.apply(headers)

    def refresh(self, request):
        self.token += '1'
      
      



Memcache:





class MemcacheFake(object):
    def __init__(self):
        self._data = {}

    def set(self, key, value):
        self._data[key] = value

    def get(self, key):
        return self._data.get(key)
      
      



, . , pylint, , , .





ยซยป

, , , ยซยป. โ€“ , . Mock , wraps



:





credentials = mock.Mock(wraps=CredentialsStub())
...
assert credentials.refresh.called
      
      



//

, . mock_x, x_mock, mocked_x, fake_x ., x. , , , . , :





mock_signer = mock.create_autospec(crypt.Signer, instance=True)
      
      



signer:





signer = mock.create_autospec(crypt.Signer, instance=True)
      
      



patch , :





@mock.patch('google.auth._helpers.utcnow')
def test_refresh_success(mock_utcnow):
    mock_utcnow.return_value = datetime.datetime.min
    ...
      
      



utcnow



:





@mock.patch('google.auth._helpers.utcnow')
def test_refresh_success(utcnow):
    utcnow.return_value = datetime.datetime.min
    ...
      
      



patch



, x_patch







utcnow_patch = mock.patch('google.auth._helpers.utcnow')
with utcnow_patch as utcnow:
    utcnow.return_value = datetime.datetime.min
    ...
      
      



, utcnow_patch



utcnow



. , , , .





, patch



, unused_x



:





@mock.patch('google.auth._helpers.utcnow')
def test_refresh_success(unused_utcnow):
    ...
      
      



helper-

. , helper- . , http-, :





def make_http(data, status=http_client.OK, headers=None):
    response = mock.create_autospec(transport.Response, instance=True)
    response.status = status
    response.data = _helpers.to_bytes(data)
    response.headers = headers or {}

    http = mock.create_autospec(transport.Request)
    http.return_value = response

    return request
      
      



:





def test_refresh_success():
    http = make_http('OK')
    assert refresh(http)

def test_refresh_failure():
    http = make_http('Not Found', status=http_client.NOT_FOUND)
    with pytest.raises(exceptions.TransportError):
        refresh(http)
      
      



pytest (https://docs.pytest.org/en/latest/fixture.html) โ€“ . , helper- , helper



. , , . , , - :





@pytest.fixture()
def server():
    server = WSGIServer(application=TEST_APP)
    server.start()
    yield server
    server.stop()
      
      



, . , , :





@pytest.fixture()
def database():
    db = database.Client()
    yield db
    db.delete(db.list_all())
      
      



โ€“ , , . , . , , urllib3



transport



:





@pytest.fixture(params=['urllib3', 'requests'])
def http_request(request):
    if request.param == 'urllib3':
        yield google.auth.transport.urllib3.Request(URLLIB3_HTTP)
    elif request.param == 'requests':
        yield google.auth.transport.requests.Request(REQUESTS_SESSION)
      
      




2021 , Django . , ยซยป Django Docker, , , .   .





"Python Developer. Professional"








All Articles