Files
Gnuboard7/tests/Unit/Benchmark/SyntheticSeederTest.php
T
HeuJung b10e89bef0 fix(core,board,ecommerce,page,gdpr,ckeditor5,kginicis,admin_basic,basic): 목록 조회·검증 계층 정비 및 감사 지적 전건 처리
목록 조회 성능 축(깊은 OFFSET·정렬·색인)과 그 검증 계층에서 계획서 전수검수와 3회에 걸친
감사가 지적한 항목을 처리했다. 세부 경위는 의 각 회차 문서에 있다.

검증 계층 — 컨트롤러가 base Request 를 직접 주입받던 확장 13곳을 전용 FormRequest 로 옮겼다.
옮기면서 기존 동작 계약은 그대로 두었다: 상한 초과 limit 을 거부하지 않고 상한까지 반환하던
공개 API, per_page 를 범위로 조정하던 관리자 목록, 미지원 period 를 year 로 해석하던 인기글
목록 모두 종전과 같은 응답을 낸다. 상한/폴백을 rules 로 승격시키면 200 이던 응답이 422 가
되어 기존 링크가 깨지므로, 규칙은 타입만 닫고 클램프·폴백은 접근자가 맡는다. period 는
접근자가 닫힌 집합만 반환해 캐시 키 공간도 함께 닫힌다.

ckeditor5 이미지 업로드만 ResponseHelper 봉투를 쓰지 않는다. 응답을 파싱하는 주체가 CDN 으로
로드되는 상위 CKEditor5 43.3.1 의 SimpleUploadAdapter 라 규약을 바꿀 수 없어, 각 응답 지점에
사유를 명시한 면제를 부착하고 근거를 API 문서에 남겼다.

하네스 — 룰 5개의 대상 경로 패턴이 매처와 맞지 않아 번들 확장 컨트롤러가 검사 대상에서
통째로 빠져 있었다. 패턴을 고치자 확장 위반 17건이 드러나 전건 처리했다. severity 오타가
요약 집계 양쪽에 안 잡혀 "0 error" 로 보고되던 문제도 런너 사전 검증으로 막았다.

정렬 게이트 대조 하네스는 관계 정렬 변형만 쓰는 저장소를 탐지하지 못한 채 통과시키고 있었다.
탐지·제외·인자 파싱을 함께 고치고 단위 테스트를 신설했다.
2026-08-02 15:29:29 +09:00

76 lines
2.9 KiB
PHP

<?php
namespace Tests\Unit\Benchmark;
use App\Benchmark\SyntheticSeeder;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use PHPUnit\Framework\Attributes\Test;
use Tests\TestCase;
/**
* 합성 시더 단위 테스트.
*
* 계측이 재려는 것은 "정렬 컬럼 인덱스를 타는 깊은 OFFSET 비용" 이다. 그러려면 프로파일이
* 정렬 기준으로 삼는 컬럼이 합성 행에도 실제로 채워져 있어야 한다. 그 컬럼이 전부 NULL 이면
* 모든 합성 행이 동률이 되어 계측 대상이 tie-break 경로로 바뀐다.
*/
class SyntheticSeederTest extends TestCase
{
// 합성 행을 직접 지우지 않고 트랜잭션 롤백으로 되돌린다. 수동 DELETE 는 쿼리가 늘고,
// 단언이 실패해 예외로 빠지면 행이 남아 다음 실행을 오염시킨다.
// (RefreshDatabase 는 마이그레이션을 다시 돌리므로 읽기 위주 검증에는 과하다.)
use DatabaseTransactions;
/**
* 정렬 대상 컬럼이 nullable 이어도 합성 행에 값이 채워지는지 검증합니다.
*
* users.created_at 은 nullable 이라 "NOT NULL + 기본값 없음" 필터에 걸리지 않는다.
* 요구 컬럼으로 넘겼는데도 비어 있으면 그 프로파일의 계측은 정렬 인덱스를 타지 않는다.
*/
#[Test]
public function it_fills_nullable_sort_columns_when_required(): void
{
$table = 'users';
$maxId = (int) (DB::table($table)->max('id') ?? 0);
app(SyntheticSeeder::class)->seed(
table: $table,
count: 5,
requiredColumns: ['created_at'],
);
$rows = DB::table($table)->where('id', '>', $maxId)->get(['id', 'created_at']);
$this->assertCount(5, $rows, '합성 행 5건이 삽입되어야 합니다.');
$this->assertSame(
0,
$rows->whereNull('created_at')->count(),
'정렬 기준 컬럼(created_at)이 NULL 인 합성 행이 있으면 계측이 동률로 무너집니다.'
);
$this->assertGreaterThan(
1,
$rows->pluck('created_at')->unique()->count(),
'정렬 기준 컬럼 값이 행마다 분산되어야 합니다(전부 같은 값이면 filesort 가 지배).'
);
}
/**
* 요구 컬럼을 지정하지 않으면 기존 동작(NOT NULL 컬럼만 채움)이 유지되는지 검증합니다.
*/
#[Test]
public function it_keeps_existing_behaviour_without_required_columns(): void
{
$table = 'users';
$maxId = (int) (DB::table($table)->max('id') ?? 0);
app(SyntheticSeeder::class)->seed(table: $table, count: 3);
$this->assertSame(
3,
DB::table($table)->where('id', '>', $maxId)->count(),
'요구 컬럼 없이도 시딩 자체는 동작해야 합니다.'
);
}
}