플러터 유닛 테스팅
- 유닛 테스팅 (Unit Testing)
첨엔 핫리로딩의 효율성이 정말 좋다보니 테스팅을 할 필요성을 못 느꼈었는데요.
점차 코드를 추가하다보니 테스트를 해야겠단 생각이 들었습니다.
이번에 테스팅을 공부하면서 다트가 정말 잘 만들어졌구나 하는 걸 느꼈습니다.
사실 다트의 테스팅도 다른 테스트와 비슷합니다. 용어가 조금 다를 뿐이죠.
이번 글을 통해 제가 개발하며 배운 테스팅을 정리해보려 합니다.
플러터에서 쓰이는 테스트 방식은 크게 3가지인데요.
유닛 테스트, 위젯 테스트, 통합 테스트입니다.
뒤로 갈수록 테스팅의 규모가 커지는 대신, 시간이 더 오래걸리죠.
이번 글에선 유닛 테스팅을 알아보도록 할께요.
1. Unit Testing
유닛 테스팅은 메소트나 클래스처럼 작은 단위를 테스트할 때 쓰입니다. 외부에 의존하지 않는 테스트를 말하죠. 보통 IO 처리를 하거나, 데이터베이스에 접근 하는 걸 외부에 의존한다고 하는데요.
외부에 의존하는 경우는 Mockito 같은 테스트 프레임워크를 써서 테스트를 합니다.
일단 다트의 기본 테스트 프레임워크를 알아보도록 할께요. Mockito는 다른 글에서 알아보도록 하겠습니다.
1.1 Unit Testing - 다트 기본 테스트 프레임워크1.1.1 설정 및 첫 테스트 실행하기
우선 test 라이브러리를 추가해주세요.
pubspec.yaml
dev_dependencies:
test: any
test 폴더에다가 테스트 파일(simple_test.dart)을 만들어주세요.
파일 이름은 항상 test로 끝나야합니다.
test/simple_test.dart
import 'package:test/test.dart';
void main() {
test('should be lowercase', () { // 어떤 테스트를 할지 설명하고,안에 있는 테스트를 실행합니다.
String hello = "Hello World";
expect(hello.toLowerCase(), "hello world"); // 테스트를 실행했을 때의 기대값과 실제값을 비교합니다.
});
}
테스트 코드는 main()에 적어주셔야합니다.
테스트 코드는 크게 test() 함수와 expect() 함수로 되어 있습니다.
test()는 테스트를 실행할 때 쓰이는 함수고, expect()는 테스트 실행값과 기대값을 비교하는 함수입니다.
그럼 테스트를 실행해보겠습니다.
이 테스트는 소문자로 잘 바뀌는지 확인해보는 테스트입니다.
flutter test test/simple_test.dart
문제없이 통과되었습니다.
그럼 테스트할 때 쓰이는 기본적인 함수들을 알아보겠습니다.
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
void main() {
test('should be lowercase', () {
String hello = "Hello World";
expect(hello.toLowerCase(), "hello world");
});
test('should contain name', () {
String hello = "Hello World, Mike";
expect(hello.contains('mike'), true); // 테스트 실패! 소문자 mike는 찾을 수 없다.
});
}
테스트 실패시 기대값과 실제값이 어떻게 다른지 보여줍니다
Expected: <true>
Actual: <false>
package:test_api expect
test/simple_test.dart 13:5 main.<fn>
어떤 점이 다른지 보여주니, 함수를 잘못 작성했다면 쉽게 고칠 수 있겠죠?
1.1.4 테스트 예제 - 덧셈, 뺄쎔 함수 테스트 해보기
덧셈 뺄쎔을 하는 함수를 만들어보고 테스트를 해보겠습니다.
group() 함수로 여러 테스트를 묶어서 테스트 해보겠습니다.
calculator.dart
class Calculator {
int add(int x, int y) => x + y;
int minus(int x, int y) => x - y;
int square(int x) => x * x;
}
test/calculator_test.dart
import 'package:test/test.dart';
void main() {
group('calculator', () {
Calculator cal = Calculator();
test('add should be equal to a + b', () {
expect(cal.add(20, 30), 50);
});
test('minus should be equal to a - b', () {
expect(cal.minus(30, 20), 10);
});
test('square should be equal to a * a', () {
expect(cal.square(10), 10 * 10);
});
});
}
3 케이스 다 통과 했습니다.
1.1.5 비동기 테스트 해보기
플러터 개발을 하다보면 비동기 데이터를 확인할 일이 많습니다.
퓨처를 어떻게 테스트 하는지 알아보겠습니다.
asynchronous_test.dart
void main() {
test('new Future.value() returns the value', () {
var value = Future.value(10);
expect(value, 10);
});
}
이대로 테스트를 실행하면 어떻게 될까요?
Expected: <10>
Actual: <Instance of 'Future<int>'>
실패하네요.
expect()의 기대값을 바꿔주면 테스트를 통과할까요?
void main() {
test('new Future.value() returns the value', () {
var value = Future.value(10);
expect(value, Future.value(10));
});
}
또 실패합니다.
Expected: <Instance of 'Future<int>'>
Actual: <Instance of 'Future<int>'>
둘 다 퓨처의 인스턴스지만 같은 인스턴스는 아니라서 실패했습니다.
퓨처를 테스트할때는 expect(실제값, 기대값) 중 기대값을 completion으로 해줘야합니다.
completion은 퓨처가 완료될 때까지 테스트를 종료하지 않도록 하죠.
테스트를 실행해볼께요.
void main() {
test('new Future.value() returns the value with completion', () {
var value = Future.value(10);
expect(value, completion(10));
});
}
테스트를 무사히 통과합니다.
여태까지 간단한 테스트를 해보았습니다.
'Flutter' 카테고리의 다른 글
Flutter - 테스트 종류 (2) | 2023.11.10 |
---|---|
Flutter - Test 2편 (2) | 2023.11.10 |
Flutter - ListView (0) | 2023.11.08 |
Flutter - Scaffold (1) | 2023.11.08 |
Flutter - MaterialApp (0) | 2023.11.08 |