반응형
flutter_testing

플러터 유닛 테스팅

  • 유닛 테스팅 (Unit Testing)

 

첨엔 핫리로딩의 효율성이 정말 좋다보니 테스팅을 할 필요성을 못 느꼈었는데요.

점차 코드를 추가하다보니 테스트를 해야겠단 생각이 들었습니다.

이번에 테스팅을 공부하면서 다트가 정말 잘 만들어졌구나 하는 걸 느꼈습니다.

사실 다트의 테스팅도 다른 테스트와 비슷합니다. 용어가 조금 다를 뿐이죠.

이번 글을 통해 제가 개발하며 배운 테스팅을 정리해보려 합니다.

 

플러터에서 쓰이는 테스트 방식은 크게 3가지인데요.

유닛 테스트, 위젯 테스트, 통합 테스트입니다.

뒤로 갈수록 테스팅의 규모가 커지는 대신, 시간이 더 오래걸리죠.

이번 글에선 유닛 테스팅을 알아보도록 할께요.

 

1. Unit Testing

유닛 테스팅은 메소트나 클래스처럼 작은 단위를 테스트할 때 쓰입니다. 외부에 의존하지 않는 테스트를 말하죠. 보통 IO 처리를 하거나, 데이터베이스에 접근 하는 걸 외부에 의존한다고 하는데요.

 

외부에 의존하는 경우는 Mockito 같은 테스트 프레임워크를 써서 테스트를 합니다.

일단 다트의 기본 테스트 프레임워크를 알아보도록 할께요. Mockito는 다른 글에서 알아보도록 하겠습니다.

 

1.1 Unit Testing - 다트 기본 테스트 프레임워크
1.1.1 설정 및 첫 테스트 실행하기

우선 test 라이브러리를 추가해주세요.

pubspec.yaml

 

test 폴더에다가 테스트 파일(simple_test.dart)을 만들어주세요.

파일 이름은 항상 test로 끝나야합니다.

 

test/simple_test.dart

테스트 코드는 main()에 적어주셔야합니다.

테스트 코드는 크게 test() 함수와 expect() 함수로 되어 있습니다.

test()는 테스트를 실행할 때 쓰이는 함수고, expect()는 테스트 실행값과 기대값을 비교하는 함수입니다.

 

그럼 테스트를 실행해보겠습니다.

이 테스트는 소문자로 잘 바뀌는지 확인해보는 테스트입니다.

문제 없이 통과 되었네요.

 

그럼 테스트할 때 쓰이는 기본적인 함수들을 알아보겠습니다.

1.1.2 다트의 테스트 함수
  • test

    • 테스트에 대한 설명과 실제 테스트 코드를 적습니다.
    • 시간 제한(timeout) 이나 테스트 환경 (브라우저, OS) 등도 적어줄 수 있습니다.
  • expect

    • expect(실제값, 기대값)
    • 테스트의 기대값과 실제값을 비교합니다.
    • 다른 언어의 assert 와 동일하다고 보시면 됩니다.
  • setup

    • 테스트를 시작하기 전에 설정을 해줍니다.
    • 테스트 단위 하나마다 실행됩니다. ( test() 함수 하나가 테스트 단위 하나에요. 한 파일에 여러 test() 가 있으면 여러번 실행됩니다. )
  • setupAll

    • 테스트 시작하기 전에 설정을 해줍니다.
    • 파일 하나에 한번만 실행됩니다. (데이터 베이스 설정할 때 쓰기 좋겠죠)
  • teardown

    • 테스트를 마치고 할 작업을 정해줍니다.
    • 테스트 단위 하나마다 실행됩니다 ( setup() 함수랑 동일합니다 )
  • teardownAll()

    • 테스트를 마치고 할 작업을 정해줍니다.
    • 파일 하나에 한번만 실행됩니다. ( setupAll() 함수랑 동일합니다 )

 

이 뿐만 아니라 테스트 시간 제한, 비동기 테스트 등 할 수 있는게 정말 많습니다.

자세한 건 다트 펍을 참고해주세요 (https://pub.dartlang.org/packages/test)

 

1.1.3 테스트 예제 - 테스트 실패 해보기

이번엔 테스트를 일부러 실패해 보겠습니다.

test/simple_test.dart

 

테스트 실패시 기대값과 실제값이 어떻게 다른지 보여줍니다.

어떤 점이 다른지 보여주니, 함수를 잘못 작성했다면 쉽게 고칠 수 있겠죠?

 

1.1.4 테스트 예제 - 덧셈, 뺄쎔 함수 테스트 해보기

덧셈 뺄쎔을 하는 함수를 만들어보고 테스트를 해보겠습니다.

group() 함수로 여러 테스트를 묶어서 테스트 해보겠습니다.

calculator.dart

 

test/calculator_test.dart

 

3 케이스 다 통과 했습니다.

 

1.1.5 비동기 테스트 해보기

플러터 개발을 하다보면 비동기 데이터를 확인할 일이 많습니다.

퓨처를 어떻게 테스트 하는지 알아보겠습니다.

asynchronous_test.dart

이대로 테스트를 실행하면 어떻게 될까요?

실패하네요.

expect()의 기대값을 바꿔주면 테스트를 통과할까요?

또 실패합니다.

둘 다 퓨처의 인스턴스지만 같은 인스턴스는 아니라서 실패했습니다.

퓨처를 테스트할때는 expect(실제값, 기대값) 중 기대값을 completion으로 해줘야합니다.

completion은 퓨처가 완료될 때까지 테스트를 종료하지 않도록 하죠.

테스트를 실행해볼께요.

 

테스트를 무사히 통과합니다.

 

여태까지 간단한 테스트를 해보았는데요.

이젠 좀 더 실용적인 예제를 테스트 해볼께요.

맞는 주민 번호와 이메일인지 확인하는 함수를 작성하고

테스트를 해보겠습니다.

 

2.이메일과 주민번호 테스트하기

2.1 테스트 예제 - 주민번호 확인하기 ( social security number validator )

주민 번호는 앞에는 생년월일, 뒤에는 성별 및 주소로 되어 있죠.

이를 확인하는 정규표현식을 작성해 보겠습니다.

field_validator.dart

정규표현식과 매칭되면 true를 반환하고 아니면 false를 반환합니다..

 

이제 함수를 테스트 해볼게요.

3가지 케이스를 테스트합니다.

911222-2110332 , 761031-1518312, 983015-1910312 를 넣어볼건데요.

 

911222-2110332 , 761031-1518312 은 true를 반환하고

983015-1910312 은 983015니 (30월이니) false를 반환해야겠죠.

정말 그런지 테스트 해볼께요.

 

test/field_validator_test.dart

 

예상대로 테스트를 통과하네요.

이해를 위해 테스트를 좀 더 해볼께요.

 

이메일을 확인하는 함수를 작성하고 테스트 해보겠습니다. .

 

2.2 테스트 예제 - 이메일 확인하기 ( email validator )

아래 코드를 봐주세요.

validateEmail()는 이메일 형식에 맞으면 true를 반환하고, 아니면 false를 반환하는 함수입니다.

 

field_validator.dart

 

테스트 케이스는 2개를 작성했습니다.

goodday@gmail.com, badday#@gmail.com 란 입력인데요.

badday#@gmail.com 은 #이 들어있어서 유효한 이메일이 아닙니다.

2 케이스 다 통과할거라고 테스트 함수를 짜면, 하나는 실패하겠죠?

정말 그런지 볼께요.

 

test/field_validator_test.dart

import 'package:test/test.dart';
import '../src/field_validator.dart';


void main() {
  group('field validator test', () {

    test("validateEmail", (){
      const String email1 = "goodday@gmail.com";

      expect(FieldValidator.validateEmail(email1), true); // 통과할거로 예상하고 통과

      const  String email2 = "badday#@gmail.com";

      expect(FieldValidator.validateEmail(email2), true , reason: '# is a not valid character'); // 통과할 거로 예상했으나 통과하지 못하기에 test fail
    });
  });
}

 

테스트 실행결과

Expected: <true>
  Actual: <false>
# is a not valid character

예상대로 이메일 badday#@gmail.com는 테스트를 통과하지 못하네요.

이번엔 expect() 에다 reason 을 적어줬습니다. reason을 적으면 테스트가 실패한 원인을 알려줍니다.

 

마무리

테스트 방식에는 크게 3가지가 있는데

이번 글에선 단위 테스트만 알아보았습니다.

플러터의 위젯 테스트, 통합 테스트는 다음 번에 알아보도록 할께요!

 

참고글 - http://dartdoc.takyam.com/articles/dart-unit-tests/

 

 

반응형

+ Recent posts