1. Introdução aos testes automatizados de API
Teste automatizado de API
Concluímos todo o desenvolvimento da interface do Larabbs e, em seguida, precisamos entregá-la a outros engenheiros para acoplamento. Ao implantar a interface no ambiente de produção, como garantir que a interface entregue esteja correta e estável? No futuro, adicionaremos novas funções ao projeto. Nesse momento, como podemos garantir que a interface ainda esteja normal após a atualização do código?
Durante o processo de desenvolvimento, usamos PostMan para testar manualmente as interfaces uma por uma, mas quando temos dezenas ou mesmo centenas de interfaces, o teste manual não será aplicável se quisermos testar essas interfaces ao mesmo tempo. A solução são os testes automatizados. Os testes automatizados são uma parte importante para garantir a qualidade do projeto. Nesta seção, vamos entender os conceitos relacionados aos testes.
teste de unidade
Teste de unidade refere-se à inspeção e verificação da menor unidade testável do software. Para PHP, geralmente testa um determinado método em uma determinada classe ou um único método. O objetivo do teste unitário é primeiro garantir que os componentes básicos de um sistema possam funcionar normalmente e que todas as partes básicas funcionem normalmente, para que o software montado não tenha problemas.
O teste de unidade é um teste em nível de código e os custos de desenvolvimento e manutenção são altos, por isso não é recomendado para equipes pequenas. Se for uma colaboração entre várias pessoas, minha tarefa é encapsular separadamente algumas funções comuns, como escrever um serviço; ou escrever um pacote de extensão para fornecer algumas interfaces de código subjacentes, como empacotar um SDK para um aplicativo de terceiros e, em seguida, unir testar é muito útil, necessário.
Existem muitos pontos de conhecimento envolvidos em testes unitários. Neste tutorial, não explicaremos os testes unitários separadamente.
Teste de integração de API
No teste de API integrado que vem com o framework Laravel, inicializamos o contexto completo da aplicação e, após preparar os dados de teste no banco de dados, podemos simular facilmente vários métodos de solicitação, chamar a interface para obter o resultado da resposta e, finalmente, afirmar se o o resultado retornado é igual ao resultado esperado .
Os testes de integração de API precisam preparar dados de teste, definir usuários, atribuir permissões de usuário e preparar dados associados para a interface de teste. Embora haja um certo custo de manutenção, em comparação com os testes unitários, o custo de manutenção é muito menor e, até certo ponto, pode garantir melhor a robustez do projeto.
Teste PostMan
Use PostMan e outras ferramentas para testes manuais. Esta é a solução de teste mais recomendada. É muito adequada para equipes pequenas, porque pode simular solicitações de usuários de forma mais realista e, na colaboração em equipe, os engenheiros de back-end podem compartilhar a interface de depuração do PostMan com os clientes Engenheiro, se houver algum problema com a interface, o engenheiro do cliente poderá testá-la sozinho.
2. Teste de integração da API Laravel
Crie uma nova pasta Vá para o diretório pai da nova pasta, $mkdir nome da pasta
Nesta seção aprendemos sobre testes de integração de API por meio de vários exemplos.
Se você estiver usando ou atualizando para o Laravel 5.7, a versão do phpunit deve ser
7.*
Unidade PHP
PHPUnit é uma estrutura leve de testes de PHP. O Laravel suporta PHPUnit para testes por padrão e configura o arquivo phpunit.xml para sua aplicação. Você só precisa executá-lo na linha de comando para testar phpunit
.
Há um pequeno erro no projeto Larabbs atual, que causará um erro ao executar o phpunit PHP Fatal error: Cannot redeclare route_class()
. Só porque há alguns problemas com a introdução do nosso método personalizado, modifique-o um pouco:
bootstrap/app.php
.
.
.
require_once __DIR__ . '/helpers.php';
.
.
.
O código anterior costumava require
introduzir um método personalizado, que pode ser introduzido repetidamente, por isso é alterado aqui require_once
.
Tente executar no diretório raiz do larabbs phpunit
$ phpunit
Criar arquivo de teste
Primeiro você precisa criar um arquivo de teste:
$ php artisan make:test TopicApiTest
Este comando criará tests/Feature
arquivos TopicApiTest.php
no diretório. Descobriremos que existem dois diretórios no diretório de testes Feature
. Unit
Como distinguir esses dois diretórios?
- Unidade - Os testes unitários são escritos do ponto de vista do programador. Eles são usados para garantir que um método específico de uma classe execute um conjunto específico de tarefas.
- Recurso - Os testes funcionais são escritos do ponto de vista do usuário. Eles garantem que o sistema se comporte conforme o usuário espera, incluindo a interação de diversos objetos, ou até mesmo uma solicitação HTTP completa.
Nossa API de teste é um teste funcional e deve ser criada no Feature
diretório.
tópico de lançamento de teste
testes/Recurso/TopicApiTest.php
<?php
namespace Tests\Feature;
use App\Models\User;
use App\Models\Topic;
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class TopicApiTest extends TestCase
{
protected $user;
public function setUp()
{
parent::setUp();
$this->user = factory(User::class)->create();
}
public function testStoreTopic()
{
$data = ['category_id' => 1, 'body' => 'test body', 'title' => 'test title'];
$token = \Auth::guard('api')->fromUser($this->user);
$response = $this->withHeaders(['Authorization' => 'Bearer '.$token])
->json('POST', '/api/topics', $data);
$assertData = [
'category_id' => 1,
'user_id' => $this->user->id,
'title' => 'test title',
'body' => clean('test body', 'user_topic_body'),
];
$response->assertStatus(201)
->assertJsonFragment($assertData);
}
}
setUp
será executado antes do início do teste, primeiro criamos um usuário e o teste testará como esse usuário.
testStoreTopic
É um usuário de teste, testando e postando tópicos. Usar $this->json pode simular convenientemente várias solicitações HTTP:
- O primeiro parâmetro é o método de solicitação, o método POST é usado para publicar o tópico;
- O segundo parâmetro - endereço de solicitação, solicitação
/api/topics
; - O terceiro parâmetro - parâmetros de solicitação, entrada ,,,,
category_id
esses três parâmetros necessários;body
title
- O quarto parâmetro - Request Header, pode ser definido diretamente
header
ou usarwithHeaders
métodos para atingir o mesmo propósito;
Descobrimos que o código gerado Token
e configurado para o usuário não será utilizado apenas , mas também serão utilizados os casos de teste de outras funções escritas no futuro, então vamos encapsulá-lo.Authorization
修改话题
删除话题
Adicione uma característica:
$ touch tests/Traits/ActingJWTUser.php
testes/Traits/ActingJWTUser.php
<?php
namespace Tests\Traits;
use App\Models\User;
trait ActingJWTUser
{
public function JWTActingAs(User $user)
{
$token = \Auth::guard('api')->fromUser($user);
$this->withHeaders(['Authorization' => 'Bearer '.$token]);
return $this;
}
}
Modifique o caso de teste para usar esta característica.
testes/Recurso/TopicApiTest.php
<?php
namespace Tests\Feature;
.
.
.
use Tests\Traits\ActingJWTUser;
.
.
.
class TopicApiTest extends TestCase
{
use ActingJWTUser;
.
.
.
public function testStoreTopic()
{
$data = ['category_id' => 1, 'body' => 'test body', 'title' => 'test title'];
$response = $this->JWTActingAs($this->user)
->json('POST', '/api/topics', $data);
$assertData = [
'category_id' => 1,
'user_id' => $this->user->id,
'title' => 'test title',
'body' => clean('test body', 'user_topic_body'),
];
$response->assertStatus(201)
->assertJsonFragment($assertData);
}
}
Desta forma, podemos facilmente usar JWTActingAs
o método para fazer login de um usuário. A resposta resultante $response
, ao assertStatus
afirmar que o resultado da resposta é 201
, assertJsonFragment
contém assertData
dados ao afirmar que o resultado da resposta é.
Execute o teste:
$ phpunit
O cartão continua reportando um erro aqui: Erro: Chamada para método indefinido Illuminate\Auth\TokenGuard::fromUser()
esperando para ser resolvido
Tópico de modificação de teste
testes/Recurso/TopicApiTest.php
.
.
.
public function testUpdateTopic()
{
$topic = $this->makeTopic();
$editData = ['category_id' => 2, 'body' => 'edit body', 'title' => 'edit title'];
$response = $this->JWTActingAs($this->user)
->json('PATCH', '/api/topics/'.$topic->id, $editData);
$assertData= [
'category_id' => 2,
'user_id' => $this->user->id,
'title' => 'edit title',
'body' => clean('edit body', 'user_topic_body'),
];
$response->assertStatus(200)
->assertJsonFragment($assertData);
}
protected function makeTopic()
{
return factory(Topic::class)->create([
'user_id' => $this->user->id,
'category_id' => 1,
]);
}
.
.
.
Adicionamos testUpdateTopic
um caso de teste. Para modificar o tópico, primeiro precisamos criar um tópico para o usuário, então adicionamos makeTopic
um tópico para gerar um tópico para o usuário atualmente testado. O código é semelhante a publicar um tópico, preparar os dados do tópico a serem modificados $editData
, chamar 修改话题
a interface, modificar o tópico recém-criado e, finalmente, afirmar que o código de status da resposta é 200
e o resultado o contém $assertData
.
Execute o teste:
$ phpunit
tópico de visualização de teste
testes/Recurso/TopicApiTest.php
.
.
.
public function testShowTopic()
{
$topic = $this->makeTopic();
$response = $this->json('GET', '/api/topics/'.$topic->id);
$assertData= [
'category_id' => $topic->category_id,
'user_id' => $topic->user_id,
'title' => $topic->title,
'body' => $topic->body,
];
$response->assertStatus(200)
->assertJsonFragment($assertData);
}
public function testIndexTopic()
{
$response = $this->json('GET', '/api/topics');
$response->assertStatus(200)
->assertJsonStructure(['data', 'meta']);
}
.
.
.
Adicionados dois usuários de teste testShowTopic
e , test e testIndexTopic
respectivamente . Essas duas interfaces podem ser acessadas sem login do usuário, portanto não há necessidade de passar Token.话题详情
话题列表
testShowTopic
Primeiro crie um tópico, depois acesse 话题详情
a interface, afirme que o código de status da resposta é 200
e os dados da resposta são consistentes com os dados do tópico recém-criados.
testIndexTopic
Acesse diretamente 话题列表
a interface, o código de status da resposta de asserção é , e há e 200
na estrutura de dados de resposta de asserção .data
meta
Execute o teste:
$ phpunit
Testar exclusão de tópico
testes/Recurso/TopicApiTest.php
.
.
.
public function testDeleteTopic()
{
$topic = $this->makeTopic();
$response = $this->JWTActingAs($this->user)
->json('DELETE', '/api/topics/'.$topic->id);
$response->assertStatus(204);
$response = $this->json('GET', '/api/topics/'.$topic->id);
$response->assertStatus(404);
}
.
.
.
Primeiro makeTopic
crie um tópico, depois DELETE
chame 删除话题
a interface por meio do método para excluir o tópico e afirme que o código de status da resposta é 204
.
Em seguida, solicite a interface de detalhes do tópico e afirme que o código de status da resposta é 404
, porque o tópico foi excluído, então ele será obtido 404
.
Execute o teste:
$ phpunit
No final, executamos 7 usuários de teste, fizemos 22 afirmações e o teste estava correto.
controle de versão de código
$ git add -A
$ git commit -m 'topic test'
3. Testes de caixa preta de terceiros
Além de testes de unidade e testes de integração, também podem ser usadas ferramentas de terceiros. Nesta seção, aprenderemos como usar o PostMan para testes de caixa preta de terceiros, que é nossa solução de teste mais recomendada.
A vantagem do teste de caixa preta de terceiros é que ele pode testar todo o sistema ao máximo.Para nossa interface API, a partir da análise do código PHP, os seguintes fatores afetarão a usabilidade da interface:
- Erros no nível do código do software;
- Erros ocorrem em softwares de terceiros utilizados pelo programa, como: cache Redis e sistema de filas, banco de dados MySQL, etc.;
- Software de sistema no servidor API, como Nginx, Cron, etc.;
- Problemas físicos no servidor API, como falha no disco rígido;
- Problemas de resolução de nomes de domínio, como erros de resolução de DNS;
O teste automatizado no nível do código tem um escopo limitado de teste. O teste de caixa preta de terceiros simula as solicitações de usuários reais e considera o servidor API como um sistema completo . Qualquer parte quebrada no sistema pode ser detectada. Além disso, este método de teste é completamente dissociado do ambiente do servidor e o custo de manutenção posterior é baixo.
Compartilhe dados da interface
PostMan nos ajuda a exportar a interface salva. Na colaboração em equipe, o engenheiro de back-end pode facilmente compartilhar os dados da interface do PostMan com o engenheiro do cliente, e o engenheiro do cliente pode testar a interface sozinho e simular a solicitação real.
Exportar coleção
Existem muitos formatos de exportação para escolher, escolhemos o recomendado pelo PostMan Collection v2.1
.
Após escolher exportar, você obterá Larabbs
o arquivo de interface com um nome de arquivo semelhante Larabbs.postman_collection.json
.
exportar variáveis de ambiente
Além dos dados da interface, também definimos algumas variáveis de ambiente, como {
{host}}
, {
{jwt_user1}}
etc., também precisamos exportá-las e compartilhá-las com outras pessoas, para que seja um ambiente completo.
Clique em Configurações no canto superior direito e selecione Manage Environments
.
Clique no download atrás do ambiente correspondente.
Os nomes dos arquivos baixados são semelhantes larabbs-local.postman_environment.json
.
Deve-se notar aqui que nosso ambiente atual larabbs-local
é nosso ambiente local. Para facilitar o uso dos engenheiros do cliente, podemos construir um ambiente Larabbs completo em um servidor de teste acessível on-line, aumentar o ambiente do servidor de teste e definir o larabbs-test
ambiente variáveis do ambiente de teste {
{host}}
. {
{jwt_user1}}
Espere, o ambiente compartilhado desta forma pode ser usado diretamente por outras pessoas.
Coleção de importação e meio ambiente
Compartilharemos os arquivos exportados Larabbs.postman_collection.json
e larabbs-local.postman_environment.json
dois arquivos com os engenheiros do cliente.
Clique no canto superior esquerdo Import
para importar arquivos da coleção.
Manage Environments
Clique em para Import
importar variáveis de ambiente.
Após a importação ser bem-sucedida, podemos depurar diretamente a interface.
Teste automatizado PostMan
PostMan nos fornece a função de teste automatizado, semelhante ao teste de interface do Laravel, PostMan pode solicitar a interface e afirmar o resultado da resposta e os dados de resposta, e então tomaremos as duas interfaces como exemplo para realizar testes 发布话题
automatizados 话题列表
.
tópico de lançamento de teste
Abra 发布话题
a interface, você verá uma Tests
aba, clique nesta aba, aparecerá uma área em branco, aqui podemos adicionar algumas afirmações para julgar o resultado da solicitação.
Preencha o seguinte conteúdo:
pm.test("响应状态码正确", function () {
pm.response.to.have.status(201);
});
pm.test("接口响应数据正确", function () {
pm.expect(pm.response.text()).to.include("id");
pm.expect(pm.response.text()).to.include("title");
pm.expect(pm.response.text()).to.include("body");
pm.expect(pm.response.text()).to.include("user_id");
pm.expect(pm.response.text()).to.include("category_id");
});
PostMan nos fornece pm.test
um método que equivale a um caso de teste. O primeiro parâmetro é o texto do prompt após a execução estar correta e o segundo parâmetro é um fechamento para executar nossa asserção.
Para o primeiro usuário de teste, avaliamos o código de status da resposta e pm.response.to.have.status(201);
afirmamos que o código de status do resultado da resposta é 201
.
Para o segundo usuário de teste, julgamos os dados de resposta afirmando pm.expect(pm.response.text()).to.include("");
que os dados de resposta devem conter um determinado campo.
Clique Send
para depurar.
Mude para Test Results
e você verá que ambos os casos de teste foram aprovados.
Lista de tópicos de teste
Da mesma forma, 话题列表
adicionamos casos de teste para a interface:
// example using response assertions
pm.test("响应状态码正确", function () {
pm.response.to.have.status(200);
});
pm.test("接口响应数据正确", function () {
pm.expect(pm.response.text()).to.include("data");
pm.expect(pm.response.text()).to.include("meta");
});
Dois casos de teste também são adicionados, afirmando que o código de status da resposta é 200
e afirmando que os dados de resposta contêm data
e meta
.
Clique Send
para depurar.
O teste passa.
teste em lote
Depois de concluir o teste do usuário para cada interface, podemos realizar testes automatizados por meio da ferramenta de teste PostMan.
Clique no canto superior esquerdo do PostMan Runner
, podemos ver a interface de teste automatizado do PostMan, podemos optar por testar o projeto inteiro ou testar um determinado diretório. Aqui selecionamos 话题
o diretório, selecionamos larabbs-local
o ambiente e executamos o teste.
Podemos ver que PostMan solicita 话题
todas as interfaces no diretório por sua vez, porque adicionamos casos de teste e asserções para 发布话题
e , para que possamos ver que os usuários de teste dessas duas interfaces foram aprovados.话题列表
Podemos adicionar casos de teste para todas as interfaces, de modo que, após a atualização da interface, ela possa ser facilmente testada por meio da ferramenta de teste automatizado do PostMan para localizar rapidamente a interface que não atende às expectativas.
4. Documentação da API
Depois de concluir todas as APIs e testes, precisamos ter um documento de interface para comodidade dos demais. Nesta seção apresentaremos o método de geração rápida de documentos API.
Carteiro
A Coleção exportada pelo PostMan já é um documento básico de interface, que pode complementar ainda mais as informações de descrição dos parâmetros da solicitação.
Claro que existem muitas desvantagens:
- Os documentos precisam ser compartilhados por meio de importação e exportação;
- É impossível descrever detalhadamente os resultados da resposta;
- Não há lugar para adicionar mais explicações sobre a interface;
Claro, usuários pagos podem desfrutar de funções mais convenientes, não discutiremos mais aqui.
Introdução
Apizza ( apizza - uma ferramenta de gerenciamento de API para geeks ) é uma ferramenta online de gerenciamento de colaboração de API. A interface e o uso são basicamente semelhantes ao PostMan, que pode ser entendido como uma versão online do PostMan.
Mas comparado ao PostMan, as funções são mais abundantes, por exemplo, podemos definir parâmetros de solicitação e tipos de parâmetros com mais detalhes.
Os dados de resposta podem ser descritos com mais detalhes.
Ele suporta arquivos de descrição no formato Markdown e podemos adicionar descrições detalhadas de chamadas para um conjunto de interfaces.
Além disso, Apizza também suporta importação direta de arquivos PostMan Collection.
Observe que atualmente apenas os arquivos de coleção do PostMan v1 são suportados. Exporte um arquivo v1 do PostMan e importe-o para o Apizza.
Depois que a exportação for bem-sucedida, você poderá ver que o documento está consistente com o PostMan.
Claro, também existem funções de colaboração em equipe e compartilhamento de documentos.
Resumir
No estágio de desenvolvimento, definitivamente usaremos o PostMan para depuração da interface, importaremos os arquivos da coleção PostMan para o Apizza e, em seguida, melhoraremos ainda mais os documentos com os membros da equipe e, finalmente, os compartilharemos com outras pessoas, o que é uma coisa conveniente e rápida.
Embora o APIdoc e o swagger sejam excelentes ferramentas de documentação, eles ainda apresentam um certo custo de aprendizado e de manutenção. Portanto, recomendamos que o PostMan seja usado em combinação com ferramentas online como Apizza para completar rapidamente a documentação da API.