ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 2화. 위젯도 테스트 코드부터
    Archiving/Flutter 2024. 1. 25. 14:13
    반응형

    1화에서는 잠시 머리를 식힐겸 유닛테스트를 진행해봤다. 켄트벡 선생님께서 말씀하신 내용도 잘 따랐고 놀랍게도 책에 나온 것처럼 된다는 사실에 웃음이 나는 경험을 했다. 그럼 이번에는 위젯을 이용한 테스트를 진행해봐야 실전 플러터 TDD라고 생각되지 않을까?!

     


     

    프로젝트를 처음 생성하면 카운터 샘플이 생성된다. test 폴더에 들어있는 widget_test.dart 를 보면 위젯 테스트 샘플 코드가 들어있다. 설레는 마음으로 가볍게 살펴보자.

     

    import 'package:flutter/material.dart';
    import 'package:flutter_test/flutter_test.dart';
    
    import 'package:flutter_widget_test/main.dart';
    
    void main() {
      testWidgets('Counter increments smoke test', (WidgetTester tester) async {
        // Build our app and trigger a frame.
        await tester.pumpWidget(const MyApp());
    
        // Verify that our counter starts at 0.
        expect(find.text('0'), findsOneWidget);
        expect(find.text('1'), findsNothing);
    
        // Tap the '+' icon and trigger a frame.
        await tester.tap(find.byIcon(Icons.add));
        await tester.pump();
    
        // Verify that our counter has incremented.
        expect(find.text('0'), findsNothing);
        expect(find.text('1'), findsOneWidget);
      });
    }

     

    앞서 작성했던 test 함수와는 다르게 testWidgets 라는 함수를 호출하고 있다. 테스트 함수를 수행하는 곳에 WidgetTester 객체가 전달되는 것이 유닛 테스트와 다른 점이다.  눈에 잘 들어오지 않지만 일단 읽어보는 것을 추천한다. 처음에는 뭐든 어색한 편이다. 

     

    필자의 글들을 보면 느끼겠지만 코드를 짤 때는 상상을 많이 해야한다. 그러니 이번에는 플러터에서 위젯테스트를 구현하면서 가상의 품질관리 담당자를 떠올려보는 걸 추천한다. 이 담당자는 처음 화면을 맞닥드리고 어떻게 해야 할지 안절부절 할 것이다. 그러니 하나 하나 알려줘야 한다. 

    • '글자' 가 쓰여져있는 것(들)을 찾아봐
    • '글자' 가 없는 것(들)을 찾아봐
    • '그림' 이 존재하는 것(들)을 찾아봐
    • '그림' 이 존재하지 않는 것(들)을 찾아봐
    • '낙인' 이 있는 것(들)을 찾아봐
    • '낙인' 이 없는 것(들)을 찾아봐

    이러한 내용을 알려주면 된다. 이러한 내용은 find 라는 객체를 통해서 해결 하는 걸 눈치 챘을 것이다.

    • find.text('0')
    • find.byIcon(Icons.add)
    • find.byKey

    이 외에도 다양한 위젯을 탐색하는 방법이 있는데 이 내용은 나중에 더 공부를 할 때 작성하는 것으로 하겠다. 이제 find 를 통해 우리가 레이아웃에 배치된 위젯들을 찾을 수 있다는 것을 확인했다. 그러면 이제 어떻게 해야하는가?

     

    Pump, 마법의 주문

    pumpWidget, pump 이 명령어는 무엇인지 많이 궁금할 것이다. 코드를 다시 봐도 굳이 tab 다음에 한번더 pump 를 호출한다. 뭔가 아리송 한 것 같지만 내면의 의미를 곰곰히 생각해보면 어거지 같겠지만 퍼 올린다는 의미를 이해할 수 있을 것이다. 일단 그런 의미는 후술 하는 것으로 하고 개발을 완료한 결과물을 품질 관리 담당자에게 주고 여기에 있는 버튼을 눌러볼까요? 라고 이야기 한뒤에 마우스나, 스마트폰을 넘기는 행위를 했다고 상상해보자. 마우스나 스마트폰을 받은 담당자는 이제 마우스를 클릭하거나 터치해서 버튼을 누르게 된다. 그러면 화면이 의도한 대로 변경이 될 것이고 기대한 결과값을 다시 확인 하면 된다.

     

    // Tap the '+' icon and trigger a frame.
    await tester.tap(find.byIcon(Icons.add));
    await tester.pump();
    
    // Verify that our counter has incremented.
    expect(find.text('0'), findsNothing);
    expect(find.text('1'), findsOneWidget);

     

    코드 상으로는 tap 은 이미 동작을 했고 로직도 수행이 된 상황이 된다. 다만 수정된 위젯 요소들과 렌더링이 처리되지 않은 상태다. 이 때 펌프질을 통해 UI 렌더링을 수행하는 행위를 한다고 읽으면 된다. pump 라는 행위는 바로 이러한 동작을 수행하는데 도움을 주는 함수이다.

     


    위젯 테스트를 간단하게 살펴보았다. 이번 포스팅이 짧은 이유는 빠르게 통합 테스트까지 마무리 하고 기본에 충실한 이야기를 해보고 싶어서다. 위젯 테스트를 수행하면서 통합테스트를 대체 할 수 있을 거라는 상상을 해본적 있는가? 그렇다고 한다면 과연 통합테스트 라는 행위는 없어도 되는 건가? 아니다. 각각의 영역에서 검증 할 수 있는 영역이 있으며 혹여라도 이 정도 제공하면 나는 충분히 코드의 품질을 보장 할 수 있을 거라고 오판하면 안된다. 

    반응형
Designed by Tistory.