기존 라라벨 애플리케이션 테스트에 소요되는 시간 줄이기 free

2019-07-31

저는 테스트를 잘하고 싶어서 꽤 시간을 많이 들여 학습한 편입니다. 아직도 잘하진 못하지만 왠만하면 테스트를 작성하려고 하고, 테스트가 없으면 좀 불안해하는 편입니다. 작년에 한 프로젝트에 참여했었는데, 그때도 가장 먼저 한 이 테스트를 작성한 이었습니다. 주요 기능들을 커버하는 테스트를 작성하기 까지 꽤 오랜 시간이 필요했습니다. 제이슨 맥크레리(Jason McCreary)가 기존 벨 애플리케이션 테스트에 소요되는 시간 줄이기(Lowering the time cost of testing existing Laravel applications)는 제목의 글을 썼기에 반가운 마음에 요약 해봤습니다. 이 글의 내용을 미리 알고 있었다면 덜 고생했을텐데 아쉽네요. ㅎㅎ


시간이 많이 드는 테스트 준비


제이슨 맥크레리는 최근에 다른 사람과 페어프로그래밍을 하게되서 기존 애플리케이션에 테스트를 작성할 이 있었다고 합니다. 그때 시간이 무척 많이 들었는데, 테스트를 준비하는데 드는 시간이 많았다고 합니다. 기존 벨 애플리케이션에서 테스트를 시작하기까지 다음과 같은 작업이 필요하다고 합니다.



  • 다양한 컴포넌트에 대한 테스트 클래스 만들기

  • 모델 팩토리 만들기

  • 모델 데이터와 관계 정의하기

  • 테스트 환경 변수 설정하기

  • 테스트 데이터베이스 설정하기


이 모든 작업을 마친다고 해도 아직 실질적인 테스트는 한 줄도 작성하지 않은 것입니다. 시간은 시간대로 썼는데 성과가 눈에 드러나지 않는 입니다. 테스트 준비에 소요되는 시간을 줄이는 방법을 몇가지 소개합니다.


모든 컨트롤러용 테스트를 한 방에 만들기


기존 애플리케이션에 테스트를 추가할 때는 우선 HTTP 테스트만 충실히 작성해도 충분합니다. 어차피 이미 잘 동작하는 애플리케이션이기 때문에 유닛 테스트가 급한 상황은 아닙니다. 우트에서 클로저로 처리를 하는 경우도 있지만 대부분의 요청은 컨트롤러로 처리할 겁니다. 벨에서는 컨트롤러 파명이 Controller로 끝나는게 관례입니다. 이를 활용해서 아래와 같이 한 번에 모든 컨트롤러용 테스트를 만들 수 있습니다.


find app/Http/Controllers -type f -name '*Controller.php' -exec sh -c 'php artisan make:test $(dirname "${1:4}")/$(basename "$1" .php)Test' sh {} \;

이로서 앞서 말한 다섯가지 준비 사항 중 첫번째 항목이었던 “다양한 컴포넌트에 대한 테스트 클래스 만들기”에 드는 시간을 많이 아낄 수 있을 것 같습니다.


벨 테스트 팩토리 제너레이터


테스트를 준비할 때 가장 시간이 많이 드는건 모델 팩토리를 작성하는 것입니다. 벨 테스트 팩토리 제너레이터는 마르셀 포시오트가 만든 패키지로써, 모든 모델에 대한 팩토리를 한 방에 만들어줍니다. 단순히 팩토리 파을 만드는 것 뿐만 아니 데이터베이스 스키마를 분석해서 모델 팩토리의 내용도 자동으로 작성해줍니다. 심지어 모델간의 관계도 분석해서 알아서 처리해줍니다. 아래와 같은 테이블이 있다면


Schema::create('lessons', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->integer('ordinal');
$table->unsignedBigInteger('course_id');
$table->timestamps();
});

이 패키지는 다음과 같은 모델 팩토리를 자동으로 만들어줍니다.


/* @var $factory \Illuminate\Database\Eloquent\Factory */

use Faker\Generator as Faker;

$factory->define(App\Lesson::class, function (Faker $faker) {
return [
'name' => $faker->name,
'ordinal' => $faker->randomNumber(),
'course_id' => function () {
return factory(App\Course::class)->create()->id;
},
];
});

이 패키지로 앞서 언급한 다섯가지 준비 사항 중 두번째와 세번째 단계에 드는 시간을 아낄 수 있습니다. 모델이 많으면 많을수록 엄청나게 시간을 아낄 수 있겠네요.


기본적인 테스트까지 자동으로 작성


제이슨 맥크레리는 여기서 한 발 더 나아가고 싶었나봅니다. 테스트 준비 작업 뿐 아니 실제 테스트를 작성하는 시간도 줄이고 싶다고 합니다. 이를 위해 Test Generator Shift 는 것을 만들기 시작했다고 하네요. 우트 정의와 컨트롤러 메서드 시그니처를 활용해서 테스트와 팩토리를 자동으로 생성되게 할 계획이고 합니다. 현재 알파 테스트를 마쳤다고 하네요.


예를들어 아래와 같은 우트가 있다면


Route::get('promotions/{code}', 'CouponController@show');

The Test Generator Shift는 다음과 같은 HTTP 테스트를 만들어줍니다.


<?php

namespace Tests\Http\Controllers;

use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;

class CouponControllerTest extends TestCase
{
use RefreshDatabase;

/** @test */
public function show_returns_an_ok_response()
{
$this->markTestIncomplete('This test case was generated by Shift and needs review.');

$coupon = factory(\App\Coupon::class)->create();

$this->get('promotions/' . $coupon->code);

$response->assertOk();

// TODO: perform additional assertions...
}
}

8월 중에 릴리즈하는 것을 목표로 한다고 하네요. 정말 기대됩니다.


기존 애플리케이션에 테스트를 추가하고 싶었지만 엄두가 안나셨던 분들은 오늘 소개한 스크립트와 벨 테스트 팩토리 제너레이터, 그리고 앞으로 나올 The Test Generator Shift를 활용하면 한결 수월하게 시작할 수 있지 않을까 싶습니다.

===

어느새 7월호의 마지막 글이네요. 컨텐트가 여러분들께 도움이 되었는지 모르겠네요. 1 1 벨 프로젝트를 실행할 수 있도록 힘을 실어주셔서 정말 감사했습니다. 8월에도 쏠쏠한 내용들 전달하도록 노력하겠습니다. 

1 1
2019년 7월 31





이현석

메쉬 코리아 개발자. 바쁜 팀장님 대신 알려주는 신입 PHP 개발자 안내서를 쓰고, 클린 아키텍처 인 PHP를 번역했습니다. 2020년에 출간될 Laravel Up & Running 2nd Edition을 번역하고 있습니다.