본문 바로가기

개발/FLUTTER

flutter unit test 하는 방법

반응형

대표이미지

Flutter에서는 테스트코드 작성을 위한 package가 있습니다. flutter_test or test 패키지인데요. 이 패키지들을 통해 unit test를 할 수 있습니다. 여기서 unit test란 모델, 함수 등 한 가지 단위를 테스트한다고 생각하시면 될 것 같습니다.

unit test의 개념인 TDD에 대한 설명은 아래 링크를 참고해주시기 바랍니다.

 

2024.01.27 - [개발/CS] - TDD 란 무엇일까?

 

TDD 란 무엇일까?

오늘은 소프트웨어 방법론 중에 하나인 TDD에 대해 알아보겠습니다. TDD란 Test Driven Development의 약자로 테스트 주도 개발이라고 합니다. 작은 단위의 테스트 케이스를 작성하고 이를 통과하는 코

programming.onebata.co.kr

오늘은 flutter_test 패키지를 통해 unit test를 하는 방법을 정리해 보겠습니다.

 

목차

1. dev_dependencies 추가


2. Test 파일 생성


3. 테스트 코드 작성


4. 전체 코드

 

dev_dependencies 추가

dev_dependencies

pubspec.yaml 파일에 dev_dependencies 영역에 다음과 같이 flutter_test package를 추가해 줍니다.

 

 

Test 파일 생성

위 사진과 같이 프로젝트 디렉터리에 기본적으로 test 폴더가 있고, 하위에 widget_test 파일이 있었을 겁니다. 저는 파일을 지우고 providers 폴더 밑에 provider 클래스를 테스트하는 test 파일을 생성하였습니다.

 

test 파일을 생성할 때 한 가지 규칙이 있는데요. 이름 끝은 _test로 끝나야 합니다.

 

테스트 코드 작성

우선 flutter_test package를 import 해주고 그 외에 필요한 라이브러리 혹은 package를 import 하면 됩니다.

 

그리고 테스트코드는 main 함수 안에 작성해야 하기 때문에 우선 main 함수를 적고 그 안에 필요한 함수나, 변수를 선언하고, test 함수를 선언합니다.

 

테스트 코드에서 사용하는 주요 함수는 test()와 expect()입니다.

 

test()

  • 첫 번째 매개변수에는 테스트에 대한 설명을 적고, 두 번째 매개변수에는 실제 테스트 코드를 적습니다.
  • 시간제한이나 테스트 환경 등도 적어줄 수 있습니다.

expect()

  • expect(실제값, 기댓값)
  • 테스트의 실제값과 기댓값을 동일한지 비교합니다.

전체 코드

 

import 'dart:convert';
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:loginscreen/model/meeting/recommend/challenge_summary.dart';

void main(){
  final List<ChallengeSummary>  challengeList = [
    ChallengeSummary(
        image: "https://cdn.emetro.co.kr/data2/content/image/2020/01/23/0540/20200123000058.jpg",
        like: false,
        tag: "스터디",
        title: "당신은 기필코 합격할 것입니다",
        date: "12.3(일)",
        duration: " 4주 간",
        time: 3,
        participants: 1,
        total: 5
    ),
    ChallengeSummary(
        image: "https://health.chosun.com/site/data/img_dir/2020/12/18/2020121801715_0.jpg",
        like: false,
        tag: "헬스",
        title: "운동량 정해서 같이 운동할 메이트 구해요 충정로역 근처에서 매일하는데 같이하실분",
        date: "12.3(일)",
        duration: " 2주 간",
        time: 3,
        participants: 1,
        total: 5
    ),
    ChallengeSummary(
        image: "https://i.namu.wiki/i/kF4DbOVxjeMVm1A7GeQKsIhgaCM6VPXSwDbsryEwglLglapp4-QxwmguseIWNTZY3ztUhmi0mS989FjoEsVAkQ.webp",
        like: false,
        tag: "독서",
        title: "독서할까?",
        date: "12.3(일)",
        duration: " 2주 간",
        time: 1,
        participants: 1,
        total: 4
    ),
  ];
  
  Future<List<ChallengeSummary>> fetchAndSetChallengeItems() async{
    final List<ChallengeSummary> challenge;
    final List<ChallengeSummary> loadedChallengeItem = [];
    try {
      final file = new File("assets/data/challenge.json");
      final extractedData = json.decode(await file.readAsString()) as Map<
          String,
          dynamic>;

      extractedData['items'].forEach((challengeItemData) {
        loadedChallengeItem.add(ChallengeSummary.fromJson(challengeItemData));
      });
    }
    catch(e){
      print(e);
    }
    finally{
      await Future.delayed(Duration(milliseconds: 800));
      return challenge = loadedChallengeItem;
    }
  }

  bool changeLike (ChallengeSummary challenge){
    if (challenge.like)
      challenge.like = false;
    else
      challenge.like = true;

    return challenge.like;
  }

  //fetchAndSetChallengeItems() : ChallengeSummary 데이터가 들어있는 json 파일을 디코딩하여 List<ChallengeSummary> 멤버에 저장한다.
  test(
      'make sure fetchAndSetChallengeItems function set valid List<ChallengeSummary> ',()  async {
    List<ChallengeSummary> providerChallengeList = await fetchAndSetChallengeItems();
    for(int i = 0; i < challengeList.length; i++){
      expect(providerChallengeList[i].image, challengeList[i].image);
      expect(providerChallengeList[i].like, challengeList[i].like);
      expect(providerChallengeList[i].tag, challengeList[i].tag);
      expect(providerChallengeList[i].title, challengeList[i].title);
      expect(providerChallengeList[i].date, challengeList[i].date);
      expect(providerChallengeList[i].duration, challengeList[i].duration);
      expect(providerChallengeList[i].time, challengeList[i].time);
      expect(providerChallengeList[i].participants, challengeList[i].participants);
      expect(providerChallengeList[i].total, challengeList[i].total);
    }
  }
  );

  //changeLike() : ChallengeSummary 객체를 입력받아서 like에는 현재 bool값을 반전시켜 저장한다
  test('make sure changeLike function change ChallengeSummary like member succesfully ', () {
    bool result = changeLike(challengeList[0]);
    expect(result, true);
  });
}

 

제가 작성한 테스트 코드는 json 자료형을 json 객체로 변환하는 함수를 테스트하는 코드입니다. 그래서 json 객체형 변수를 선언해 놓고, json 변환하는 함수를 선언해서 json 함수가 반환하는 json 객체가 선언해 놓은 json 객체형 변수와 동일한지 비교합니다.

 

또 한 가지 코드는 model의 멤버변수를 변환하는 함수를 테스트하는 코드입니다.

 

첫 번째 테스트 코드에서 중요한 것은 클래스형 객체는 그냥 비교하게 되면 같은 타입 일지라도 서로 다른 인스턴스이기 때문에 다르다고 테스트 결과가 나옵니다.

 

따라서 위와 같은 방식으로 클래스에 operator와 hashCode 함수를 오버라이드 하거나,

equatable 패키지

equatable 패키지를 사용하여 Equatable 클래스를 상속받고 props를 오버라이드 해줘야 합니다.

참고 사이트

https://pub.dev/packages/test

https://pub.dev/packages/equatable

반응형