Olá!
Meu nome é Timofey, sou desenvolvedor Python na equipe da Cyan Platform. Nossa equipe está desenvolvendo ferramentas para desenvolvedores de produtos. São as bibliotecas: cliente HTTP, servidor Web, bibliotecas de acesso ao banco de dados e ferramentas de monitoramento para microsserviços e o site como um todo, integração com CI / CD e muito mais.
, — .
...
, , . , , , , , .
, - -. . , - . , , .
Code-coverage
. diff-coverage: pull-request , . — 80%, , pull-request diff-coverage . .
, , , . , , - : diff, :
API-, : dev, beta prod, .
-
coverage — -. ?
-, :
. , , , .
. 2 3 — . , , . , - “” .
- . -, . : — !
, . .
API . API Application Programming Interface, , HTTP API, RabbitMQ / Kafka .
, , HTTP Mock Server, , .
:
- , API, RabbitMQ, .
- , .
- , black box, , .
- , -.
, Python, C#, frontend NodeJS . Python pytest. Python- -, C#- API-. pytest , .
-?
! , :
- , -. .
- . - , — .
- , -, CI-pipeline .
- , , , , , .
, .
, API , — -.
, . , app.toml. , :
[[dependency]]
type = "postgres"
alias = "users"
[[dependency]]
type = "rabbitmq"
command line :
cian-functional-test-utils deps up
, docker-compose.yml docker-compose up -d
. “” docker-compose, Elasticsearch, . , alias
.
conftest.py :
@pytest.fixture(scope='session', autouse=True)
async def start(runner, pg):
# ,
# health-check.
await runner.start_background_python_web()
# HTTP API, RabbitMQ ,
await runner.start_background_python_command('save-users-consumer')
@pytest.fixture(scope='session')
async def pg(postgres_service):
db = await postgres_service.create_database_by_alias('users')
# `pathlib.Path` .
await db.execute_scripts(Path('database_schemas') / 'postgres.sql')
return db
! :
async def test_v1_get_user(http, pg): # pg conftest.py
# arrange
await pg.execute('INSERT INTO users (id, name) VALUES (1, "Bart")')
# act
response = await http.request('GET', '/v1/get-user/', params={'id': 1})
# assert
assert response.status == 200
assert response.data == {'id': 1, 'name': 'Bart'}
PostgreSQL MsSQL, Cassandra, Redis, Elasticsearch.
HTTP API , :
async def test_save_users_consumer(pg, queue_service):
# arrange
# RabbitMQ ,
# , .
await queue_service.wait_consumer(queue='save-users')
# act
await queue_service.publish(
exchange='users',
routing_key='user.created',
payload={'id':1, 'name': 'Bart'},
)
await asyncio.sleep(0.5) # ,
# assert
row = await pg.fetchrow('SELECT name FROM users WHERE id = 1')
assert row['name'] == 'Bart'
RabbitMQ ( ), . ? RabbitMQ .
, , , .
, . . - API . “” : , HTTP-, Management API. , API, . , .
HTTP-. .
HTTP
HTTP- mountebank. ( ) HTTP. , , :
@pytest.fixture(scope='session')
async def users_mock(http_mock_service):
# , ,
# URL .
return await http_mock_service.make_microservice_mock('users')
def test_something(users_mock):
# arrange
stub = await users_mock.add_stub(
method='GET',
path='/v1/get-user/',
response=MockResponse(body={'firstName': 'Bart', 'lastName': 'Simpson'}),
)
# act
# do something
# assert
# , ?userId=234
request = (await stub.get_requests())[0]
assert request.params['userId'] == '234'
stub, 404. mountebank . , , 404 , 404, , . , ( 404). , .
mountebank , . . :
- recordRequests — , , ;
-
--debug
— .
, session , HTTP-. start
, , autouse=True
. - , http-, .
, :
- , ;
- statsd graphite ;
- RabbitMQ , .
, , , , .
, .
, Sphinx. reStructuredText , , , .
:
- , ;
- , C#-;
- ;
- API Reference, .
, , , .
Type annotations
Python – . , , — . PEP 484.
pytest PyCharm, IDE , :
pytest IDE Jetbrains Python Community Edition. C#- Rider — , IDE, .
, . , Open Source.
, , , :
- ;
- ;
- ;
- , , -.
- , , , , .
, , , .
.