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
Как и обещал завершаю серию постов про gRPC статьей в телеграф)
С вас лайк, ну а кто зашел сюда случайно, то подписка)
Всем привет)
Я чутка приболел, поэтому особо сил написать, что-то умное нет, если вы не знаете я планирую курс по базам данных, и по генерации кода проектов автотестов.
В рамках этой деятельности я чутка переписал и дополнил API, которое может стать неплохой песочницей, чтобы потренироваться писать интеграционные автотесты.
Ну и совершенно бесплатно делюсь с вами)
Register API - для регистрации и активации пользователя в системе
Mail API - для получения писем пользователей куда приходят токены для активации и смены информации пользователя
Auth API - для получения авторизационного токена с целью хождения например в Account API
Account API - позволяет изменять информацию о пользователе а так же удалять пользователя
Users API - имеет два кэшированных метода, позволяющие обработать ситуации с кэшом
Для почтового сервера так же есть frontend
Ну и для самого приложения тоже , но обычно для апи тестов в нем нет особой необходимости.
Привет, все самое основное для работы тестировщика с 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 заканчиваю, если есть какие вопросы пишите)
Кстати решил обновить фотом канала как это делают другие айтишники как вам?
👍 - нормас фотка
💩 - верни фотку как было
🔥 - пост огонь
https://t.me/aqa_engineer_community
Мне тут внезапно показалось что нам может не хватать живого общения, поэтому состряпал чатик с темами, думаю там тоже можно будет обсуждать насущные проблемы да и просто общаться, надеюсь чат со временем обрастет полезными тредами, в общем велкам)
Очень важное и полезное дополнение про отличие генераторов и итераторов.
Всем привет! Как вы знаете я люблю делать скидки на обучение в рандомный момент, но главное заранее, чтобы те кто регулярно читает мой канал и самые быстрые имели какое-то преимущество)) А так как мне лень писать новый пост, я скопипащу старый, но вставлю…
Давайте теперь поговорим о том, как же нам выполнить 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 на сегодня все!
Продолжаем тему по 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 клиента.
🌟 Учись у лучших и становись экспертом в автоматизации тестирования! 🌟 Ты уже имеешь опыт в тестировании, но чувствуешь, что не хватает знаний для уверенной работы с фреймворками и решениями? Хочешь прокачать свои навыки до уровня разработчика и научиться…
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