API
Testes de Factories - AgrSis
Testes de Factories - AgrSis
Como Testar as Factories
1. Via Tinker (Recomendado)
# Iniciar container
docker-compose up -d
# Acessar Tinker
docker exec -it agrsis_api php artisan tinker
Testes Básicos:
// 1. Testar UserFactory
$user = User::factory()->create();
echo "User ID: {$user->id}, Nome: {$user->name}, Email: {$user->email}\n";
// 2. Testar CustomerFactory PF
$customerPF = Customer::factory()->pf()->create();
echo "Cliente PF: {$customerPF->nome}, CPF: {$customerPF->cpf_cnpj}\n";
// 3. Testar CustomerFactory PJ
$customerPJ = Customer::factory()->pj()->create();
echo "Cliente PJ: {$customerPJ->nome}, CNPJ: {$customerPJ->cpf_cnpj}\n";
// 4. Testar SupplierFactory
$supplier = Supplier::factory()->create();
echo "Fornecedor: {$supplier->nome}, CNPJ: {$supplier->cnpj}\n";
// 5. Testar ProductFactory
$product = Product::factory()->create();
echo "Produto: {$product->descricao}\n";
// 6. Testar OrderFactory
$order = Order::factory()->create();
echo "Pedido ID: {$order->id}, Cliente: {$order->customer->nome}\n";
// 7. Testar SubscriptionPlanFactory
$plan = SubscriptionPlan::factory()->basic()->create();
echo "Plano: {$plan->nome}, Valor: R$ {$plan->valor_mensal}\n";
// 8. Testar TransactionFactory
$transaction = Transaction::factory()->entrada()->create();
echo "Transação: {$transaction->descricao}, Valor: R$ {$transaction->valor}\n";
// 9. Testar múltiplos registros
$users = User::factory()->count(5)->create();
echo "Criados {$users->count()} usuários\n";
// 10. Testar States combinados
$userInativo = User::factory()->produtor()->inactive()->create();
echo "User inativo: {$userInativo->name}, Status: " . ($userInativo->status ? 'Ativo' : 'Inativo') . "\n";
2. Via Testes Automatizados
Criar arquivo: tests/Unit/FactoryTest.php
<?php
namespace Tests\Unit;
use Tests\TestCase;
use App\Models\User;
use App\Models\Customer;
use App\Models\Supplier;
use App\Models\Product;
use App\Models\Order;
use App\Models\SubscriptionPlan;
use App\Models\Transaction;
use Illuminate\Foundation\Testing\RefreshDatabase;
class FactoryTest extends TestCase
{
use RefreshDatabase;
public function test_user_factory(): void
{
$user = User::factory()->create();
$this->assertDatabaseHas('users', [
'id' => $user->id,
'email' => $user->email,
]);
}
public function test_user_factory_admin_state(): void
{
$user = User::factory()->admin()->create();
$this->assertEquals('admin', $user->perfil);
$this->assertTrue($user->status);
}
public function test_customer_factory_pf(): void
{
$customer = Customer::factory()->pf()->create();
$this->assertEquals(1, $customer->tipo); // TIPO_PESSOA_FISICA
$this->assertNotNull($customer->cpf_cnpj);
$this->assertEquals(11, strlen(preg_replace('/\D/', '', $customer->cpf_cnpj)));
}
public function test_customer_factory_pj(): void
{
$customer = Customer::factory()->pj()->create();
$this->assertEquals(2, $customer->tipo); // TIPO_PESSOA_JURIDICA
$this->assertNotNull($customer->cpf_cnpj);
$this->assertEquals(14, strlen(preg_replace('/\D/', '', $customer->cpf_cnpj)));
}
public function test_supplier_factory(): void
{
$supplier = Supplier::factory()->create();
$this->assertDatabaseHas('suppliers', [
'id' => $supplier->id,
'cnpj' => $supplier->cnpj,
]);
}
public function test_product_factory_creates_product_type(): void
{
$product = Product::factory()->create();
$this->assertNotNull($product->productType);
$this->assertNotNull($product->product_type_id);
}
public function test_order_factory_creates_customer(): void
{
$order = Order::factory()->create();
$this->assertNotNull($order->customer);
$this->assertNotNull($order->customer_id);
}
public function test_subscription_plan_basic_state(): void
{
$plan = SubscriptionPlan::factory()->basic()->create();
$this->assertEquals('Básico', $plan->nome);
$this->assertEquals(99.90, $plan->valor_mensal);
$this->assertEquals(10, $plan->limite_pedidos);
}
public function test_subscription_plan_premium_state(): void
{
$plan = SubscriptionPlan::factory()->premium()->create();
$this->assertEquals('Premium', $plan->nome);
$this->assertEquals(599.90, $plan->valor_mensal);
$this->assertNull($plan->limite_pedidos); // ilimitado
}
public function test_transaction_factory_entrada(): void
{
$transaction = Transaction::factory()->entrada()->create();
$this->assertEquals('entrada', $transaction->tipo);
}
public function test_transaction_factory_saida(): void
{
$transaction = Transaction::factory()->saida()->create();
$this->assertEquals('saida', $transaction->tipo);
}
public function test_multiple_factories(): void
{
$users = User::factory()->count(10)->create();
$this->assertEquals(10, $users->count());
$this->assertDatabaseCount('users', 10);
}
public function test_factory_with_custom_attributes(): void
{
$user = User::factory()->create([
'email' => 'teste@agrsis.com',
'name' => 'Usuário Teste',
]);
$this->assertEquals('teste@agrsis.com', $user->email);
$this->assertEquals('Usuário Teste', $user->name);
}
public function test_inactive_state(): void
{
$user = User::factory()->inactive()->create();
$this->assertFalse($user->status);
}
public function test_combined_states(): void
{
$user = User::factory()->produtor()->inactive()->create();
$this->assertEquals('produtor', $user->perfil);
$this->assertFalse($user->status);
}
}
Rodar os testes:
# Todos os testes
php artisan test
# Com Docker
docker exec agrsis_api php artisan test
# Apenas testes de Factory
php artisan test --filter FactoryTest
# Com coverage
php artisan test --coverage
3. Via Seeder (Popular Banco)
Criar arquivo: database/seeders/TestDataSeeder.php
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Customer;
use App\Models\Supplier;
use App\Models\Product;
use App\Models\ProductType;
use App\Models\Brand;
use App\Models\Order;
use App\Models\SubscriptionPlan;
use App\Models\State;
use App\Models\AccessType;
class TestDataSeeder extends Seeder
{
public function run(): void
{
$this->command->info('Criando tipos de acesso...');
AccessType::factory()->cliente()->create();
AccessType::factory()->fornecedor()->create();
AccessType::factory()->administrador()->create();
$this->command->info('Criando usuários...');
User::factory()->admin()->create(['email' => 'admin@agrsis.com']);
User::factory()->produtor()->count(10)->create();
User::factory()->fornecedor()->count(5)->create();
$this->command->info('Criando clientes...');
Customer::factory()->pf()->count(20)->create();
Customer::factory()->pj()->count(10)->create();
$this->command->info('Criando fornecedores...');
Supplier::factory()->count(15)->create();
Supplier::factory()->withSite()->count(5)->create();
$this->command->info('Criando tipos de produtos e marcas...');
ProductType::factory()->count(8)->create();
Brand::factory()->count(10)->create();
$this->command->info('Criando produtos...');
Product::factory()->count(50)->create();
$this->command->info('Criando pedidos...');
Order::factory()->count(30)->create();
Order::factory()->urgent()->count(5)->create();
$this->command->info('Criando planos de assinatura...');
SubscriptionPlan::factory()->basic()->create();
SubscriptionPlan::factory()->professional()->create();
SubscriptionPlan::factory()->premium()->create();
$this->command->info('Criando estados...');
State::factory()->count(27)->create();
$this->command->info('Dados de teste criados com sucesso!');
}
}
Rodar o seeder:
# Resetar banco e popular
php artisan migrate:fresh --seed --seeder=TestDataSeeder
# Com Docker
docker exec agrsis_api php artisan migrate:fresh --seed --seeder=TestDataSeeder
Resultados Esperados
UserFactory
- ✅ CPF válido gerado
- ✅ Email único
- ✅ Senha hasheada
- ✅ Celular no formato brasileiro
- ✅ States funcionando (admin, produtor, fornecedor, inactive)
CustomerFactory
- ✅ PF: CPF com 11 dígitos
- ✅ PJ: CNPJ com 14 dígitos
- ✅ Nome/Razão Social adequados ao tipo
- ✅ Data de nascimento apenas para PF
- ✅ Email e telefone únicos
SupplierFactory
- ✅ CNPJ válido
- ✅ Nome da empresa
- ✅ Email corporativo
- ✅ Site opcional
- ✅ Status ativo por padrão
ProductFactory
- ✅ Cria ProductType automaticamente
- ✅ Descrição do produto gerada
- ✅ Status ativo por padrão
OrderFactory
- ✅ Cria Customer automaticamente
- ✅ Data limite de cotação futura
- ✅ Raio de fornecimento definido
- ✅ States funcionando (urgent, rejected, inactive)
SubscriptionPlanFactory
- ✅ States específicos (basic, professional, premium)
- ✅ Valores corretos por plano
- ✅ Limites configurados
- ✅ Recursos em JSON
TransactionFactory
- ✅ Valores financeiros corretos
- ✅ States de tipo (entrada, saida)
- ✅ States de status (pending, approved, rejected)
- ✅ Data de transação gerada
Problemas Comuns
1. Erro "Class 'Database\Factories\xxxFactory' not found"
Solução:
composer dump-autoload
php artisan optimize:clear
2. Erro de validação CPF/CNPJ
Causa: Faker pode gerar CPF/CNPJ com formato mas sem validação de dígitos.
Solução: Use bibliotecas específicas ou configure o Faker corretamente.
3. Erro de relacionamento
Causa: Tentar criar relacionamento sem a foreign key.
Solução: Use o factory que cria automaticamente:
// ❌ Errado
$order = Order::factory()->create(['customer_id' => 999]);
// ✅ Correto
$order = Order::factory()->create(); // Cria customer automaticamente
// ✅ Ou
$customer = Customer::factory()->create();
$order = Order::factory()->create(['customer_id' => $customer->id]);
Checklist de Validação
- UserFactory cria usuários válidos
- CustomerFactory diferencia PF e PJ
- SupplierFactory gera CNPJ válido
- ProductFactory cria ProductType relacionado
- OrderFactory cria Customer relacionado
- SubscriptionPlanFactory com states corretos
- TransactionFactory com tipos e status
- States combinados funcionam
- Multiple factories (count) funcionam
- Atributos customizados funcionam
Próximos Passos
- Rodar testes automatizados
- Popular banco de desenvolvimento
- Validar dados gerados
- Criar factories adicionais conforme necessidade
- Implementar testes de integração
Criado em: 2025-12-04 Versão: 1.0