【Flutter】大丈夫、テストは怖くないよ

Dart

概要

どうも、@daiki1003です!

テスト、怖くないですか?
面倒くさくないですか?

分かりますよ。

この記事は、そんなあなたのテストへの恐怖心を取り除くために執筆しました。

こんなの出せたら、かっこいいですよね。
大丈夫です、この記事を読んでいただければ誰でも出せるようになります!

本記事の構成

・ファイルの作り方、お作法
・テストの記述
・テストの単位
・テストの実行
・coverage

大体、この様な構成で書いて行きます。
最短でテストを動かせる様になる事を最優先するため、
基本的な知識をすっ飛ばすこともあるかと思いますが、
その辺は他の記事も参考にしながら勉強してみてください。

Flutterにおけるテストファイルの作り方・お作法

さて、まずはテストファイルを作らないことには始まらないので早速作ってみましょう。

ファイルの作り方

ルート階層に存在している、testフォルダ以下に
テストを記述するファイルを作成します。

基本的に、どんなファイル名でどんな階層でもテストは実行出来ますが。
少しだけお作法があるので守りましょう。
後の自分や仲間を守ることになります。

ファイルを作る際のお作法

ファイル末尾を_test.dartにする

hoge_repository.dartのテストファイル名はhoge_repository_test.dartにしましょう。

test階層以下をlib階層以下と同等にする

lib/hoge/repository/fuga_repository.dartのテストのファイル階層はtest/hoge/repository/fuga_repository_test.dartにしましょう。

Flutterにおけるテストの記述

さて、ファイルを作ったところで早速テストを書いてみましょう。

まず、雛形です。

import 'package:test/test.dart';

void main() {

}

テストファイルは必ず、main関数を持ちます。
この中にテストを記述していきます。

一つ一つのテストの記述

仮に、一つテストを記述してみましょう。

test('variable test', () {
  var sampleValue = 'sample';
  expect(sampleValue, 'sample');
});

割と直感的ですよね?

test(テスト名, () {
  // 前処理
  expect(処理や変数, 処理による結果や変数の期待値);
});

テストの一つ一つはこの様な書式で記述します。

testと言う関数を記述することで、
一つのテストを作る事が出来ます。

そして、この中に

この処理をしたらまたはこの値はこうなってほしい

と言う意味を持つexpect関数を0個以上記述します。
全てが「こうなってほしい」を満たすことによってテストが一つ通った (Passed) と言うことになります。

Flutterにおけるテストの単位

groupを使いこなそう

test('add test', () {
  expect(42 + 42, 84);
});

test('minus test', () {
  expect(42 - 42, 0);
}):

以上2つのテストがあるとします。
問題なく、通りそうですね。
これで終わりでも良いんですが、この2つ良くみてみると両方とも
整数値に対する処理を行っていますよね?

こう言う場合は、group関数を使ってまとめる事が出来ます。

group('integer test', () {
  test('add test', () {
    expect(42 + 42, 84);
  });
  test('minus test', () {
    expect(42 - 42, 0);
  });
});

記述式はtestと一緒で第一引数に名前、第二引数に実行するテストです。

groupによるメリット?

group化をすることにより、実行結果を以下の様に見やすくする事が出来ます。

この場合、まだ数が少ないのでメリットを感じにくいかもしれませんが
数が多くなってくるとより顕著になってきます。

Flutterにおけるテストの実行

それでは、ここまで書けたところでテストを実行してみましょう。

import 'package:test/test.dart';

void main() {
  group('integer test', () {
    test('add test', () {
      expect(42 + 42, 84);
    });
    test('minus test', () {
      expect(1 / 0, double.infinity);
    });
  });
}

コマンドによる実行

全テスト実行

$flutter test
00:03 +2: All tests passed! 

指定ファイルのみの実行

$flutter test [test_file_name]
00:02 +2: All tests passed! 

指定したテストのみの実行

$flutter test --plain-name 'test_name' [test_file_name]

例えば

$flutter test --plain-name 'minus test' test/widget_test.dart
00:01 +1: All tests passed!  

coverage

coverageとは?

テストについて調べていると、テストカバレッジやcoverageなんて
言葉が目に入ってくると思います。
これは、全プログラムの実行フローに対してどこまでテストによって保証されているかを示す率です。

ちょっと具体例を出してみましょう。

int add(int a, int b) {
  return a + b;
}
test('add test', () {
  expect(add(1, 2), 3);
});

この場合、coverageは100%となります。

では、以下の場合はどうでしょう?

int divide(int numerator, int denominator) {
  if (denominator != 0) {
    return numerator / denominator;
  } else {
    return double.nan;
  }
}
test('divide test', () {
  expect(divide(4, 2), 2);
});

この場合、coverageは50%となります。
なんとなく分かりましたか?
else文の方の処理を通らないので、2個のうち1つだけがテストで保証されている状態、
つまり50%となります。

coverageの出し方

では、Flutterでどうやってこのcoverageを出すのでしょうか?

$flutter test --coverage

と、実行したいテストに--coverageを付け足してあげるだけです。

ですが、これを実行すると

coverage/lcov.infoと言う何やら怪しいファイルが生成されるだけです。
しかも、中を見ても良く分からない…。

でも安心してください。
ここまで来ればもうちょっとで、最初に示した表が出せるのでもう一踏ん張りです!

coverageの可視化

lcovのインストール

このファイルを解析するための、ツールを一つ下記コマンドでインストールします。

$brew install lcov

これが終わり次第、以下を実行してみてください。

$genhtml coverage/lcov.info -o coverage/result

こちらが実行終わりましたら、-oで指定したフォルダが
生成されているはずです。

この中にあるindex.htmlをブラウザで表示すると
最初に示した表が表示されるはずです!

いかがでしたでしょうか?
テストへの恐怖心が少しでも減ってくれれば嬉しいです!

また、ここ分からなかったよ!とかがあれば気楽に@daiki1003まで
リプライお待ちしております!

誰かのお役に立てば。

Twitterフォローお願いします

「次回以降も記事を読んでみたい!」
「この辺分からなかったから質問したい!」

そんな時は、是非@daiki1003のフォローお願いします♪

また、記事がとても役に立ったと思う人は
コーヒーを奢っていただけると非常に嬉しいです!

コメント

タイトルとURLをコピーしました