Валерий | AQA Engineer | Автотестирование на Python | REST, gRPC, GraphQL

Description
Сделаю из тебя классного backend-automation QA на Python.

• 200+ учеников, курс по автоматизации тестирования Rest API
• Senior Python developer | AQA lead, 6 лет в IT

📩 @valeriy_menshikov
Advertising
We recommend to visit
HAYZON
HAYZON
5,791,257 @hayzonn

👤 𝐅𝐨𝐮𝐧𝐝𝐞𝐫: @Tg_Syprion
🗓 ᴀᴅᴠᴇʀᴛɪsɪɴɢ: @SEO_Fam
Мои каналы: @mazzafam

Last updated 1 month, 1 week ago

Architec.Ton is a ecosystem on the TON chain with non-custodial wallet, swap, apps catalog and launchpad.

Main app: @architec_ton_bot
Our Chat: @architec_ton
EU Channel: @architecton_eu
Twitter: x.com/architec_ton
Support: @architecton_support

Last updated 1 month ago

Канал для поиска исполнителей для разных задач и организации мини конкурсов

Last updated 1 month, 3 weeks ago

2 months ago
Как и обещал завершаю серию постов …

Как и обещал завершаю серию постов про gRPC статьей в телеграф)
С вас лайк, ну а кто зашел сюда случайно, то подписка)

TG-сообщество | Обучение |

2 months ago

Всем привет)

Я чутка приболел, поэтому особо сил написать, что-то умное нет, если вы не знаете я планирую курс по базам данных, и по генерации кода проектов автотестов.

В рамках этой деятельности я чутка переписал и дополнил API, которое может стать неплохой песочницей, чтобы потренироваться писать интеграционные автотесты.

Ну и совершенно бесплатно делюсь с вами)

Register API - для регистрации и активации пользователя в системе
Mail API - для получения писем пользователей куда приходят токены для активации и смены информации пользователя
Auth API - для получения авторизационного токена с целью хождения например в Account API
Account API - позволяет изменять информацию о пользователе а так же удалять пользователя
Users API - имеет два кэшированных метода, позволяющие обработать ситуации с кэшом

Для почтового сервера так же есть frontend
Ну и для самого приложения тоже , но обычно для апи тестов в нем нет особой необходимости.

TG-сообщество | Обучение |

2 months, 1 week ago

Привет, все самое основное для работы тестировщика с gRPC API мы с вами обсудили, у нас осталась только тема с ошибками.

В gRPC как и в REST реализацию отправки ошибок можно сделать по разному.
Рассмотрим первый вариант, когда у нас успешный статус и сообщение об ошибке в теле ответа, например:

```
// Для ответа с ошибкой описывается специальное поле c описанием ошибки.
message MessageResponse {
repeated Message messages = 1;
optional Error error = 2;
}

message Message {
bytes body = 1;
}

message Error {
ErrorCode code = 1;
string description = 2;
}

enum ErrorCode {
FirstError = 0;
SecondError = 1;
}
```

В Python тесте мы работаем в таком случае как с обычным сообщением:

```
response: MessageResponse = grpc_stub.SendMessage(...)

assert not response.HasField("error"), "Сообщение не должно содержать ошибку"

```

Второй случай - это когда у нас не успешное выполнение запроса и кастомное сообщение об ошибке, контракт которой так же описан в proto файле например:

// Для этого сценария у нас так же описывается мессадж сообщения, например message RPCStatusDetails { bool permanent\_err = 1; uint32 reconnect\_after\_ms = 2; }

Работать в коде с таким типом ошибок сложнее, потому что нам нужно перехватить exception сериализовать его в объект RPCStatusDetails, и работать с ним дальше, например:

```
from grpc_status import rpc_status

try:
response = grpc_stub.SendMessage(...)
except grpc.RpcError as error:
status = rpc_status.from_call(error)
for detail in status.details:
if detail.Is(rpc_status_details_pb2.RPCStatusDetails.DESCRIPTOR):
error_info_detail = rpc_status_details_pb2.RPCStatusDetails()
detail.Unpack(error_info_detail)
wait_time_ms = error_info_detail.reconnect_after_ms
error = error_info_detail.permanent_err
assert wait_time_ms == 0
assert error is False
```

И третий вид это обычное исключение - самый базовый вариант.
Работа с ним может быть так же как в примере выше, но без распаковки сообщения.

```
import grpc

NOT_EXPECTED_STATUS = {grpc.StatusCode.PERMISSION_DENIED, grpc.StatusCode.RESOURCE_EXHAUSTED}

try:
response = grpc_stub.SendMessage(...)
except grpc.RpcError as error:
assert error.code not in NOT_EXPECTED_STATUS
```

В этом посте мы рассмотрели базовые варианты работы с исключениями в ответе сервера.

На этом серию постов по gRPC заканчиваю, если есть какие вопросы пишите)

Кстати решил обновить фотом канала как это делают другие айтишники как вам?

👍 - нормас фотка
💩 - верни фотку как было

🔥 - пост огонь

2 months, 1 week ago

https://t.me/aqa_engineer_community
Мне тут внезапно показалось что нам может не хватать живого общения, поэтому состряпал чатик с темами, думаю там тоже можно будет обсуждать насущные проблемы да и просто общаться, надеюсь чат со временем обрастет полезными тредами, в общем велкам)

2 months, 1 week ago

Очень важное и полезное дополнение про отличие генераторов и итераторов.

2 months, 2 weeks ago

Всем привет! Как вы знаете я люблю делать скидки на обучение в рандомный момент, но главное заранее, чтобы те кто регулярно читает мой канал и самые быстрые имели какое-то преимущество)) А так как мне лень писать новый пост, я скопипащу старый, но вставлю…

2 months, 2 weeks ago

Давайте теперь поговорим о том, как же нам выполнить RPC-процедуры и что для этого нужно.

Мы с вами закончили на протофайле.
Следующим шагом необходимо сгенерировать клиентскую часть. Для этого нужно сделать следующие действия.

Установить gRPC

```
pip install grpcio

```

Далее нам потребуется установить gRPC tools:

gRPC tools включают компилятор протоколов protobuf (protoc) и специальный плагин для генерации кода сервера и клиента из определений сервисов .proto.

```
pip install grpcio-tools

```

Следующим шагом нужно сгенерировать код.
Это делается следующей командой, в которой нужно указать пути к протофайлам и пути, где сохранить сгенерированный код:

```
$ grpc_tools.protoc -I../../protos --python_out=. --pyi_out=. --grpc_python_out=. ../../protos/helloworld.proto

```

Для протофайла:

```
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}

```

У нас получится примерно следующее (ну и там, конечно, будет еще много кода для реализации серверной части):

```
class GreeterStub(object):

def \_\_init\_\_(self, channel): self.SayHello = channel.unary\_unary( '/helloworld.Greeter/SayHello', request\_serializer=helloworld\_pb2.HelloRequest.SerializeToString, response\_deserializer=helloworld\_pb2.HelloReply.FromString, \_registered\_method=True) self.SayHelloAgain = channel.unary\_unary( '/helloworld.Greeter/SayHelloAgain', request\_serializer=helloworld\_pb2.HelloRequest.SerializeToString, response\_deserializer=helloworld\_pb2.HelloReply.FromString, \_registered\_method=True)

```

После этого мы уже можем создать канал и отправить первый запрос.

```
def run():
with grpc.insecure_channel('localhost:50051') as channel:
stub = helloworld_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)
response = stub.SayHelloAgain(helloworld_pb2.HelloRequest(name='you'))
print("Greeter client received: " + response.message)

```

Обратите внимание, что в данном примере используется insecure_channel. В gRPC еще есть защищенный канал secure_channel. Для работы с ним нужно уметь устанавливать, например, SSL-сертификаты, но способ создания примерно такой же.

На этом про gRPC на сегодня все!

2 months, 2 weeks ago

Продолжаем тему по gRPC.

Что такое protofile?

Протофайл это такой файл который описывает схему целевого сервиса, без него невозможно сгенерировать код и создать  gRPC сервис.

Если вы когда нибудь рассматривали swagger схему то примерно представляете, что это такое.

Грубо это структурированное текстовое описание, о том как называется сервис, набор его методов, входные и выходные контракты. 

Давайте рассмотрим пример gRPC сервиса, который использовался у меня в курсе с gRPC.

```
// Синтаксис протофайла

syntax = "proto3";

// Название пакета, необходимо, если у нас есть зависимости от других протофайлов для понимания что они находятся в одном пакете, а так же разделения если у нас повторяются контракты и методы у двух API например V1 и V2

package account_proxy;

// Импорты типов из других протофайлов
import 'google/protobuf/empty.proto';
import 'google/protobuf/timestamp.proto';
import 'google/protobuf/wrappers.proto';

// Название сервиса
service AccountServiceProxy {

// Название метода (Модель запроса), (Модель ответа)
rpc Login(LoginRequest) returns (LoginResponse);

// Для пустого значения есть тоже свой тип, здесь он возвращается в ответе
rpc Logout(LogoutRequest) returns (google.protobuf.Empty);

// Клиентский стриминовый метод имеет в качестве реквеста слово stream
rpc RegisterAccountClientStream(stream RegisterAccountRequest) returns (RegisterAccountClientStreamResponse);

// Серверный стрим имеет в ответе слово stream
rpc GetAccountsServerStream(google.protobuf.Empty) returns (stream User);

// Дуплексный стрим имеет в реквесте и ответе слово stream
rpc GetAccountsByLoginDuplexStream(stream GetAccountsByLoginRequest) returns (stream GetAccountsByLoginResponse);
}
```

Теперь про сами контракты, я уже ранее приводил примеры их описания, но как говориться повторение, мать учения:

```
// Здесь все довольно просто, название модели(мессаджа), названия, типы полей и их айдишники (они нужны для кодирования соообщения, пост об этом был выше)

message LoginRequest {
string login = 1;
string password = 2;
bool remember_me = 3;
}
```

Стоит отметить как указывается модель с вложенными объектами и имеющая повторяющиеся объекты аналог листа с объектами.

```
message PagingResult {
int32 total_pages_count = 1;
int32 total_entities_count = 2;
int32 current_page = 3;
int32 page_size = 4;
int32 entity_number = 5;
}

message User {
string login = 1;
google.protobuf.StringValue medium_picture_url = 3;
google.protobuf.StringValue small_picture_url = 4;
google.protobuf.StringValue status = 5;
TimestampValue online = 7;
google.protobuf.StringValue name = 8;
google.protobuf.StringValue location = 9;
TimestampValue registration = 10;
}

// Здесь используется слово repeated, тобишь повторяется))

message GetAccountsResponse {
repeated User accounts = 1;
PagingResult paging = 2;
}
```

Аналог JSON будет такой:

{ "accounts": [ { "login": "", "medium\_picture\_url": "", "small\_picture\_url": "", "status": "", "online": "2024\-10\-23", "name": "", "location": "", "registration": "2024\-10\-23", } ], "paging": { "total\_pages\_count": 0, "total\_entities\_count": 0, "current\_page": 0, "page\_size": 0, "entity\_number": 0 } }

В общем и целом описание такой схемы это первый шаг для создания gRPC сервиса.
Тестировщики и пользователи сервиса используют протофайлы для генерации gRPC клиента.

2 months, 3 weeks ago

🌟 Учись у лучших и становись экспертом в автоматизации тестирования! 🌟 Ты уже имеешь опыт в тестировании, но чувствуешь, что не хватает знаний для уверенной работы с фреймворками и решениями? Хочешь прокачать свои навыки до уровня разработчика и научиться…

We recommend to visit
HAYZON
HAYZON
5,791,257 @hayzonn

👤 𝐅𝐨𝐮𝐧𝐝𝐞𝐫: @Tg_Syprion
🗓 ᴀᴅᴠᴇʀᴛɪsɪɴɢ: @SEO_Fam
Мои каналы: @mazzafam

Last updated 1 month, 1 week ago

Architec.Ton is a ecosystem on the TON chain with non-custodial wallet, swap, apps catalog and launchpad.

Main app: @architec_ton_bot
Our Chat: @architec_ton
EU Channel: @architecton_eu
Twitter: x.com/architec_ton
Support: @architecton_support

Last updated 1 month ago

Канал для поиска исполнителей для разных задач и организации мини конкурсов

Last updated 1 month, 3 weeks ago