File manager - Edit - /var/www/html/homologBancodetalentos/tests/Feature/TalentBank/LegacyMigrationIntegrityTest.php
Back
<?php namespace Tests\Feature\TalentBank; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Schema; use Tests\TestCase; /** * Valida a integridade dos dados após uma execução real do talent-bank:legacy-migrate. * * ⚠️ Estes testes NÃO modificam o banco — apenas lêem e assertam. * Rodá-los antes de executar a migração vai resultar em skips (tabelas vazias). * * Execute depois de: * php artisan talent-bank:legacy-migrate --sql-dump=tests/dadosantigosbt/siati_app.sql * * Suite: php artisan test --filter LegacyMigrationIntegrityTest */ class LegacyMigrationIntegrityTest extends TestCase { /** Conexão alvo (banco BT novo) */ private string $con; protected function setUp(): void { parent::setUp(); $this->con = (string) config('talent_bank_legacy_import.target_connection', config('database.default')); } // ───────────────────────────────────────────────────────────────────────── // Contagens mínimas (sanity) // ───────────────────────────────────────────────────────────────────────── /** @test */ public function deve_existir_pelo_menos_um_candidato_migrado(): void { $count = DB::connection($this->con)->table('candidates')->count(); $this->assertGreaterThan(0, $count, 'A tabela candidates deve conter registros após a migração.'); } /** @test */ public function deve_existir_pelo_menos_uma_empresa_migrada(): void { $count = DB::connection($this->con)->table('companies')->count(); $this->assertGreaterThan(0, $count, 'A tabela companies deve conter registros após a migração.'); } // ───────────────────────────────────────────────────────────────────────── // Integridade de chave primária / unicidade // ───────────────────────────────────────────────────────────────────────── /** @test */ public function nao_deve_haver_cpfs_duplicados_em_candidates(): void { $duplicates = DB::connection($this->con) ->table('candidates') ->selectRaw('cpf, COUNT(*) as total') ->groupBy('cpf') ->havingRaw('COUNT(*) > 1') ->get(); $this->assertCount(0, $duplicates, 'CPFs duplicados encontrados: ' . $duplicates->pluck('cpf')->implode(', ')); } /** @test */ public function nao_deve_haver_cnpjs_duplicados_em_companies(): void { $duplicates = DB::connection($this->con) ->table('companies') ->selectRaw('cnpj, COUNT(*) as total') ->groupBy('cnpj') ->havingRaw('COUNT(*) > 1') ->get(); $this->assertCount(0, $duplicates, 'CNPJs duplicados encontrados: ' . $duplicates->pluck('cnpj')->implode(', ')); } /** @test */ public function nao_deve_haver_legacy_ids_duplicados_em_job_listings(): void { if (! Schema::connection($this->con)->hasColumn('job_listings', 'legacy_id')) { $this->markTestSkipped('Coluna legacy_id não existe em job_listings.'); } $duplicates = DB::connection($this->con) ->table('job_listings') ->whereNotNull('legacy_id') ->selectRaw('legacy_id, COUNT(*) as total') ->groupBy('legacy_id') ->havingRaw('COUNT(*) > 1') ->get(); $this->assertCount(0, $duplicates, 'legacy_ids duplicados em job_listings: ' . $duplicates->pluck('legacy_id')->implode(', ')); } /** @test */ public function nao_deve_haver_candidaturas_duplicadas(): void { $duplicates = DB::connection($this->con) ->table('job_listing_candidate') ->selectRaw('job_listing_id, candidate_id, COUNT(*) as total') ->groupBy('job_listing_id', 'candidate_id') ->havingRaw('COUNT(*) > 1') ->get(); $this->assertCount(0, $duplicates, "Par (job_listing_id, candidate_id) duplicado em job_listing_candidate."); } // ───────────────────────────────────────────────────────────────────────── // Integridade referencial de FKs // ───────────────────────────────────────────────────────────────────────── /** @test */ public function neighbourhood_ids_de_candidates_existem_em_neighbourhoods(): void { $orphans = DB::connection($this->con) ->table('candidates as c') ->leftJoin('neighbourhoods as n', 'c.neighbourhood_id', '=', 'n.id') ->whereNotNull('c.neighbourhood_id') ->whereNull('n.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} candidatos com neighbourhood_id sem correspondência."); } /** @test */ public function gender_ids_de_candidates_existem_em_genders(): void { $orphans = DB::connection($this->con) ->table('candidates as c') ->leftJoin('genders as g', 'c.gender_id', '=', 'g.id') ->whereNotNull('c.gender_id') ->whereNull('g.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} candidatos com gender_id sem correspondência."); } /** @test */ public function marital_status_ids_de_candidates_existem_em_marital_statuses(): void { $orphans = DB::connection($this->con) ->table('candidates as c') ->leftJoin('marital_statuses as m', 'c.marital_status_id', '=', 'm.id') ->whereNotNull('c.marital_status_id') ->whereNull('m.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} candidatos com marital_status_id sem correspondência."); } /** @test */ public function occupation_ids_de_candidates_existem_em_occupations(): void { $orphans = DB::connection($this->con) ->table('candidates as c') ->leftJoin('occupations as o', 'c.occupation_id', '=', 'o.id') ->whereNotNull('c.occupation_id') ->whereNull('o.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} candidatos com occupation_id sem correspondência."); } /** @test */ public function ethnicity_ids_de_candidates_existem_em_ethnicities(): void { $orphans = DB::connection($this->con) ->table('candidates as c') ->leftJoin('ethnicities as e', 'c.ethnicity_id', '=', 'e.id') ->whereNotNull('c.ethnicity_id') ->whereNull('e.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} candidatos com ethnicity_id sem correspondência."); } /** @test */ public function neighbourhood_ids_de_companies_existem_em_neighbourhoods(): void { $orphans = DB::connection($this->con) ->table('companies as c') ->leftJoin('neighbourhoods as n', 'c.neighbourhood_id', '=', 'n.id') ->whereNotNull('c.neighbourhood_id') ->whereNull('n.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} empresas com neighbourhood_id sem correspondência."); } /** @test */ public function company_ids_de_job_listings_existem_em_companies(): void { $orphans = DB::connection($this->con) ->table('job_listings as j') ->leftJoin('companies as c', 'j.company_id', '=', 'c.id') ->whereNull('c.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} vagas com company_id sem correspondência."); } /** @test */ public function candidate_ids_em_job_listing_candidate_existem_em_candidates(): void { $orphans = DB::connection($this->con) ->table('job_listing_candidate as jc') ->leftJoin('candidates as c', 'jc.candidate_id', '=', 'c.id') ->whereNull('c.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} candidaturas com candidate_id sem correspondência."); } /** @test */ public function job_listing_ids_em_job_listing_candidate_existem_em_job_listings(): void { $orphans = DB::connection($this->con) ->table('job_listing_candidate as jc') ->leftJoin('job_listings as j', 'jc.job_listing_id', '=', 'j.id') ->whereNull('j.id') ->count(); $this->assertSame(0, $orphans, "{$orphans} candidaturas com job_listing_id sem correspondência."); } // ───────────────────────────────────────────────────────────────────────── // Dados obrigatórios / formato // ───────────────────────────────────────────────────────────────────────── /** @test */ public function todos_candidates_tem_cpf_com_11_digitos(): void { $invalid = DB::connection($this->con) ->table('candidates') ->whereRaw('LENGTH(cpf) != 11') ->orWhereRaw("cpf REGEXP '[^0-9]'") ->count(); $this->assertSame(0, $invalid, "{$invalid} candidatos com CPF fora do formato (11 dígitos numéricos)."); } /** @test */ public function todos_companies_tem_cnpj_com_14_digitos(): void { $invalid = DB::connection($this->con) ->table('companies') ->whereRaw('LENGTH(cnpj) != 14') ->orWhereRaw("cnpj REGEXP '[^0-9]'") ->count(); $this->assertSame(0, $invalid, "{$invalid} empresas com CNPJ fora do formato (14 dígitos numéricos)."); } /** @test */ public function nenhum_candidate_tem_cpf_nulo_ou_vazio(): void { $invalid = DB::connection($this->con) ->table('candidates') ->where(function ($q) { $q->whereNull('cpf')->orWhere('cpf', ''); }) ->count(); $this->assertSame(0, $invalid, "{$invalid} candidatos com CPF nulo ou vazio."); } /** @test */ public function nenhum_candidate_tem_name_nulo_ou_vazio(): void { $invalid = DB::connection($this->con) ->table('candidates') ->where(function ($q) { $q->whereNull('name')->orWhere('name', ''); }) ->count(); $this->assertSame(0, $invalid, "{$invalid} candidatos sem nome."); } /** @test */ public function nenhum_company_tem_cnpj_nulo_ou_vazio(): void { $invalid = DB::connection($this->con) ->table('companies') ->where(function ($q) { $q->whereNull('cnpj')->orWhere('cnpj', ''); }) ->count(); $this->assertSame(0, $invalid, "{$invalid} empresas com CNPJ nulo ou vazio."); } /** @test */ public function desired_payment_nao_excede_o_maximo_do_decimal_12_2(): void { $over = DB::connection($this->con) ->table('candidates') ->where('desired_payment', '>', 9999999999.99) ->count(); $this->assertSame(0, $over, "{$over} candidatos com desired_payment acima do máximo decimal(12,2)."); } /** @test */ public function min_payment_nao_excede_o_maximo_do_decimal_12_2(): void { $over = DB::connection($this->con) ->table('candidates') ->where('min_payment', '>', 9999999999.99) ->count(); $this->assertSame(0, $over, "{$over} candidatos com min_payment acima do máximo decimal(12,2)."); } /** @test */ public function nenhum_job_listing_tem_spots_total_negativo(): void { $invalid = DB::connection($this->con) ->table('job_listings') ->where('spots_total', '<', 0) ->count(); $this->assertSame(0, $invalid, "{$invalid} vagas com spots_total negativo."); } // ───────────────────────────────────────────────────────────────────────── // Consistência de coluna legada ethicity → ethnicity_id // ───────────────────────────────────────────────────────────────────────── /** @test */ public function coluna_ethnicity_string_nao_deve_mais_existir_em_candidates(): void { $hasLegacyColumn = Schema::connection($this->con)->hasColumn('candidates', 'ethnicity'); $this->assertFalse($hasLegacyColumn, 'A coluna legada "ethnicity" (varchar) ainda existe em candidates — a migration de conversão não foi executada.'); } /** @test */ public function coluna_ethnicity_id_deve_existir_em_candidates(): void { $hasFkColumn = Schema::connection($this->con)->hasColumn('candidates', 'ethnicity_id'); $this->assertTrue($hasFkColumn, 'A coluna ethnicity_id (FK) não existe em candidates.'); } // ───────────────────────────────────────────────────────────────────────── // Colunas legadas de companies // ───────────────────────────────────────────────────────────────────────── /** @test */ public function colunas_legadas_de_companies_devem_existir(): void { foreach (['occupation_area', 'county', 'cnae', 'module_id', 'module_name'] as $col) { $this->assertTrue( Schema::connection($this->con)->hasColumn('companies', $col), "Coluna '{$col}' não existe em companies — execute php artisan migrate." ); } } // ───────────────────────────────────────────────────────────────────────── // Resumo estatístico (informativo, nunca falha) // ───────────────────────────────────────────────────────────────────────── /** @test */ public function exibe_resumo_estatistico_da_migracao(): void { $candidates = DB::connection($this->con)->table('candidates')->count(); $companies = DB::connection($this->con)->table('companies')->count(); $jobs = DB::connection($this->con)->table('job_listings')->count(); $applications = DB::connection($this->con)->table('job_listing_candidate')->count(); $withNeighbourhood = DB::connection($this->con)->table('candidates')->whereNotNull('neighbourhood_id')->count(); $withEthnicity = DB::connection($this->con)->table('candidates')->whereNotNull('ethnicity_id')->count(); $withOccupation = DB::connection($this->con)->table('candidates')->whereNotNull('occupation_id')->count(); // Apenas garante que o teste roda — a saída é informativa fwrite(STDOUT, PHP_EOL . PHP_EOL . " ┌─ Resumo pós-migração ────────────────────────┐" . PHP_EOL . sprintf(" │ Candidatos: %6d │", $candidates) . PHP_EOL . sprintf(" │ Empresas: %6d │", $companies) . PHP_EOL . sprintf(" │ Vagas: %6d │", $jobs) . PHP_EOL . sprintf(" │ Candidaturas: %6d │", $applications) . PHP_EOL . " ├─ Qualidade dos dados ───────────────────────┤" . PHP_EOL . sprintf(" │ Cands c/ bairro: %6d / %-6d │", $withNeighbourhood, $candidates) . PHP_EOL . sprintf(" │ Cands c/ etnia: %6d / %-6d │", $withEthnicity, $candidates) . PHP_EOL . sprintf(" │ Cands c/ ocup.: %6d / %-6d │", $withOccupation, $candidates) . PHP_EOL . " └─────────────────────────────────────────────┘" . PHP_EOL . PHP_EOL ); $this->assertTrue(true); } }
| ver. 1.4 |
Github
|
.
| PHP 8.3.28 | Generation time: 0.02 |
proxy
|
phpinfo
|
Settings