SlideShare a Scribd company logo
Flutterで単体テストを行う方法とGitHub
Actionsを使った自動化
KBOYのFlutter大学 勉強会 2021/02/24
はじめに
このスライドの内容は以下の記事をかみ砕いて説明するものになります。
・Flutterで単体テストを書く :
 https://qiita.com/tokkun5552/items/ede8460bef4892f48e37
・【Flutter】Providerで最低限のDIを行ってテスタブルなコードにリファクタリングする :
 https://qiita.com/tokkun5552/items/7af34769104e94f50745
・【Flutter】GitHubActionsでテストと静的解析を自動化する
 https://qiita.com/tokkun5552/items/2eb6793501c152dabf33
・サンプルコードの GitHubリポジトリ
tokku5552/TODOAppSample-Flutter: A sample Todo App with Provider 
なぜテストするのか
結論:ソフトウェアの品質を高めるため
ソフトウェアの品質が下がる要因
・人間が書いているので間違いや考慮漏れは起こる→仕方がないこと
・ある場所に変更を加えることで、別の場所に影響を及ぼしバグが生まれる
テストが品質を上げる理由
・考慮漏れや間違いが起きにくくなる(客観的に見ることが出来る)
・変更時にテストして、動きが変わっていないことを確かめる
品質向上とリリースのスピードはトレードオフ
「Done is better than perfect」 → 完璧を目指すよりもまず終わらせろ
とはいえ全く動かさずにリリースするわけにはいかない
品質の落としどころ
・ベータ版としてリリース → ユーザにテストしてもらう
・モンキーテスト → テストケースを決めずに適当にクリックしたり入力したりしてみる
選択肢として
ビジネスロジックの自動テストを考えてみる
Flutterでのテストことはじめ
Flutterにおけるテストの種類
Flutterには3種類のテストがある
公式ページ:https://flutter.dev/docs/cookbook/testing
・Unit Test   
・Widget Test 
・Integration Test
いわゆる単体テスト。関数、メソッド、クラスの検証を行う
Widgetが正しく生成されるかのテスト。
結合テスト。シナリオを書いてエミュレータ上で自動操作によるテス
トが行える。
Flutterにおけるテストの種類
Flutterには3種類のテストがある
公式ページ:https://flutter.dev/docs/cookbook/testing
・Unit Test   
・Widget Test 
・Integration Test
いわゆる単体テスト。関数、メソッド、クラスの検証を行う
Widgetが正しく生成されるかのテスト。
結合テスト。シナリオを書いてエミュレータ上で自動操作によるテス
トが行える。 今回は主に、実装コストと効果の
バランスが一番よさそうな
Unit Testを扱う
UnitTestの準備
・パッケージの導入
 pubspec.yamlにflutter_testが追加されていること
※実際はtestパッケージがあれば良いが、
 flutter_testパッケージに含まれる
Unitテストの書き方と実行方法
プロジェクトルートの
testフォルダの下に
XXX_test.dartファイルを作成
import 'package:flutter_test/flutter_test.dart' ;
import
'package:todo_app_sample_flutter/data/todo_item.dart' ;
void main() {
group('TodoItemのゲッターのテスト ', () {
final TodoItem todoItem = TodoItem(
id: 0,
title: 'title',
body: 'body',
createdAt: DateTime (2020, 1, 1),
updatedAt: DateTime (2020, 1, 1),
isDone: true,
);
test('idのテスト', () {
expect (todoItem.getId, 0);
});
Unitテストの書き方と実行方法
プロジェクトルートの
testフォルダの下に
XXX_test.dartファイルを作成
import 'package:flutter_test/flutter_test.dart' ;
import
'package:todo_app_sample_flutter/data/todo_item.dart' ;
void main() {
group('TodoItemのゲッターのテスト ', () {
final TodoItem todoItem = TodoItem(
id: 0,
title: 'title',
body: 'body',
createdAt: DateTime (2020, 1, 1),
updatedAt: DateTime (2020, 1, 1),
isDone: true,
);
test('idのテスト', () {
expect (todoItem.getId, 0);
});
main関数の中に
実際のテストを記載
test(‘テストケース名’,(){
 実際のテスト処理
 expect(結果,期待する値);
});
group()でテストケースを
まとめることが出来る。
テスト実行
1. テストファイルを右クリック
2. 実行→tests in XXXX
デバッグの画面が開いて
結果が表示される
ここからが本題
class MemoDetailModel extends ChangeNotifier {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseFirestore firestore = FirebaseFirestore.instance;
Future addMemo() async {
final memo = Memo( ~~ );
   ~~何かデータ追加前にチェックしたりとか~~
final collection = firestore.collection('users');
final user = auth.currentUser;
if (user != null) {
collection.doc(user.uid).collection('memos').add({
'title': memo.title,
'updatedAt': memo.updatedAt,
'happenedAt': memo.happenedAt,
});
}
notifyListeners();
}
}
よくありそうなChangeNotifierを
継承したドメインモデル
ビジネスロジックを実装しているので
単体テストを行いたいが、
右のような状態ではテスト出来ない。
どこが問題?
なぜテスト出来ない?
・FirebaseAuthやFirestoreの
 インスタンスを生成している
 ※main()内でイニシャライズが必要
・addMemo()ではバリデーションや、
 データ追加前の正当性チェックなどを 
行っているが、同時に Firebaseの
 通信処理も行ってしまっている
class MemoDetailModel extends ChangeNotifier {
final FirebaseAuth auth = FirebaseAuth.instance;
final FirebaseFirestore firestore = FirebaseFirestore.instance;
Future addMemo() async {
final memo = Memo( ~~ );
   ~~何かデータ追加前にチェックしたりとか~~
final collection = firestore.collection('users');
final user = auth.currentUser;
if (user != null) {
collection.doc(user.uid).collection('memos').add({
'title': memo.title,
'updatedAt': memo.updatedAt,
'happenedAt': memo.happenedAt,
});
}
notifyListeners();
}
}
テストを行いやすくするために
・初期化が必要な外部パッケージ(DBやFirebaseなど)を
 直接使っているclassはテストしにくい。
※できないわけではない: cloud_firestore_mocks (https://pub.dev/packages/cloud_firestore_mocks)
・でもビジネスロジックなので、データをUI等から受け取って、
 加工して追加・更新 という処理になるのは必至では・・・?
テストを行いやすくするために
・初期化が必要な外部パッケージ(DBやFirebaseなど)を
 直接使っているclassはテストしにくい。
※できないわけではない: cloud_firestore_mocks (https://pub.dev/packages/cloud_firestore_mocks)
・でもビジネスロジックなので、データをUI等から受け取って、
 加工して追加・更新 という処理になるのは必至では・・・?
解決策:分離して疎結合にする!
ソフトウェアアーキテクチャの話
ビジネスロジックの集約と依存関係の分離
・例えばUIのクラスにすべてのロ
ジックを詰め込んで実装すること
もできるが、それをやってしまうと
一つのクラスが肥大化してしまう



・肥大化したクラスはメンテナンス
しづらく、読みにくく、テストしにく
い

Robert C. Martin著 Clean Architecture 達人に学ぶソフトウェアの構造と設計
ビジネスロジックの集約と依存関係の分離
・例えばUIのクラスにすべてのロ
ジックを詰め込んで実装すること
もできるが、それをやってしまうと
一つのクラスが肥大化してしまう



・肥大化したクラスはメンテナンス
しづらく、読みにくく、テストしにく
い

Robert C. Martin著 Clean Architecture 達人に学ぶソフトウェアの構造と設計
テスタブルなコードにするために
考えを少しだけ取り入れることにする
オブジェクト指向の話
・オブジェクト指向とは何か?と言う話はしません
・オブジェクト指向っぽいプログラミングのテクニックを少し使って
 今までテストできなくなってしまっていたコードを
 リファクタリングすることに注力します
キーワード:インターフェース、実装、抽象クラス、継承
【Flutter】Providerで最低限のDIを行ってテスタブルなコードにリファクタリングする
https://qiita.com/tokkun5552/items/7af34769104e94f50745
インターフェース
・メソッドの実装を強制する仕組み
・メソッドだけ定義して実際の処理は書かない
→内部でDB、Firebase等の処理を書くこともない。
(依存しない)
・インターフェースを実装したクラスは、
インターフェースに定義されているメソッドを
実装しなければならない
→メソッドだけを外部から見ると、全く同じ動きをする
interface Hoge{
void doHoge();
}
class HogeImpl implements Hoge{
@override
public void doHoge() {
// 実際の処理
}
}
インターフェース(Javaでの例)
インターフェースを実装した例
インターフェース
・メソッドの実装を強制する仕組み
・メソッドだけ定義して実際の処理は書かない
→内部でDB、Firebase等の処理を書くこともない。
(依存しない)
・インターフェースを実装したクラスは、
インターフェースに定義されているメソッドを
実装しなければならない
→メソッドだけを外部から見ると、全く同じ動きをする
interface Hoge{
void doHoge();
}
class HogeImpl implements Hoge{
@override
public void doHoge() {
// 実際の処理
}
}
インターフェース(Javaでの例)
インターフェースを実装した例
ただしDartにはインターフェースが
ないので、今回はabstract というのを使う
※implicit interfaceという便利な機能があるが
話がややこしくなるので割愛
インターフェースの使い方
・コンストラクタで
 インターフェースを受け取る
・インターフェースにはメソッドの
 決まりが書いてあるので、
 記載のあるメソッドは
 そのまま使うことが出来る
class TodoItemDetailModel extends ChangeNotifier {
TodoItemDetailModel ({
@required TodoItemRepository todoItemRepository ,
}) : _todoItemRepository = todoItemRepository ;
final TodoItemRepository _todoItemRepository ;
Future <void> add() async {
if (todoTitle == null || todoTitle .isEmpty) {
final Error error = ArgumentError ('タイトルを入力してください。
');
throw error;
}
await _todoItemRepository .create(
~~
);
notifyListeners ();
}
https://github.com/tokku5552/TODOAppSample-Flutter/blob/v1.3/lib/presentation/todo_item_detail/todo_item_detail_model.dart
インターフェースの使い方
・コンストラクタで
 インターフェースを受け取る
・インターフェースにはメソッドの
 決まりが書いてあるので、
 記載のあるメソッドは
 そのまま使うことが出来る
class TodoItemDetailModel extends ChangeNotifier {
TodoItemDetailModel ({
@required TodoItemRepository todoItemRepository ,
}) : _todoItemRepository = todoItemRepository ;
final TodoItemRepository _todoItemRepository ;
Future <void> add() async {
if (todoTitle == null || todoTitle .isEmpty) {
final Error error = ArgumentError ('タイトルを入力してください。
');
throw error;
}
await _todoItemRepository .create(
~~
);
notifyListeners ();
}
https://github.com/tokku5552/TODOAppSample-Flutter/blob/v1.3/lib/presentation/todo_item_detail/todo_item_detail_model.dart
外部通信など(DBやFirebaseを使う処理)はリ
ポジトリーというクラスに集約して、
ビジネスロジックから切り離す
ビジネスロジックはインターフェースに
依存する。(具体的な実装に依存しない。)
では、実際の処理はどう呼ばれる?
依存関係とDIの話
・ここで登場するのがDI(Dependency Injection)
 よく「依存性の注入」と訳されるが、
 「依存オブジェクトの注入」と考えた方が分かりやすい。
・先の例のように依存するオブジェクトを
 コンストラクタなどで外から受け取るように実装する
依存関係とDIの話
TodoItemDetailModel
field TodoItemRepository
Interface TodoItemRepository
TodoItemRepositoryImpl
依存
注入
実装
ProviderでDIする
・注入の処理をまとめて書くためのクラスをDIコンテナーと言う
・Flutterの場合get_itというDIコンテナーがある
get_it | pub.dev : https://pub.dev/packages/get_it
・get_itを使っても良いが、Providerの機能でもDIのようなことは出来るので、
 今回はProviderを使う
ProviderでDIする
・例えばmainの直下などで、
 右図のように定義する
・providersの中はProviderでも、
 StreamProviderでも、     
 ChangeNotifierProviderでも
 定義できる。
・create:でImplの方を渡す
void main() {
runApp(
MultiProvider
(
providers: [
Provider
<TodoItemRepository
>(
create: (_) => TodoItemRepositoryImpl
(),
)
],
child: App
(),
),
);
}
ProviderでDIする
・modelを生成する場所(例えば
 page内のChangeNotifierProvider)
 でコンストラクタに渡す。
・先ほどmainで定義した
 Providerは、定義した場所より
 下の階層のcontextから
 context.read<型>()
 で呼び出せる
ChangeNotifierProvider <TodoItemDetailModel >(
create: (_) => TodoItemDetailModel (
todoItemRepository:
context .read<TodoItemRepository >(),
),
Providerの詳細 参考:https://qiita.com/kabochapo/items/a90d8438243c27e2f6d9
Flutterにおけるcontext
・FlutterはWidgetをツリー状に連ねて書いていく
・そのツリーの中で自分が今いる場所を表す
・HogeWidgetのbuildで引数として受け取るBuildContextには
 Scaffoldやそれより先祖の情報は入っているが、
 FugaWidgetの情報は入ってない
・今回の例だとcontext.read<>()を記載するよりも
 先祖でProviderを呼ばなければいけない
main
Material
App
Scaffold
Hoge
Widget
FugaW
idget
DIを行うと、テストの時に差し替えられる
・アプリで使用するリポジトリの実装
 と、テストでの実装を別々に書ける
・test側の実装は、DBを呼ばず
 インメモリのDBとして記述する
・XXX_test.dartの中で直接渡せばよい
テスト用Repositoryの実装の例
・DBのインスタンスは生成しない
・実際のデータは_data
・アプリ側と同様に
 TodoItemRepositoryを実装する
class TodoItemRepositoryMemImpl implements TodoItemRepository {
final _data = <int, TodoItem>{};
 ~~
@override
Future<TodoItem> find({@required int id}) {
return Future.value(_data[id]);
}
 ~~
テスト側で使う例
・テスト用のrepositoryを
 直接インスタンス化する
・それを直接modelに渡す
・テストの中でrepositoryを
 直接操作することが可能
void main() {
final repository = TodoItemRepositoryMemImpl ();
final model =
  TodoItemDetailModel (todoItemRepository: repository );
final dummyDate = DateTime.now();
テスタブルなコードにするまとめ
・テストを行いたいclassから依存オブジェクトを排除する。
 例:Firestore 、 FirebaseAuth、sqflite 、SharedPreferences
・上記のようなものを扱うRepositoryを定義して、
 インターフェースと実装に分ける
・Providerでrepositoryの実装をコンストラクタで渡す
・テスト用のrepositoryを書く
テスト実行を自動化しよう
テスト自動化のメリット
・ローカルで毎回テストしてもいいが面倒くさい
・テストの結果がGitHub上に残る
 ・後になってバグが見つかった時に、どの時点まで正しかったのか追える
・プルリクをレビューする際の目安になる
 ・ビジネスロジックのレビューは単体テストだけ見れば正しいかどうかわかる
 ・ロジックに考慮漏れがあれば、レビュアーがテストを追加して
  担当者がテストを通過できるように修正する とかも可能
GitHub Actionsでテスト自動化
・プロジェクト直下に.github/workflowsというフォルダを作成し、その中にyamlファイル
を置いていきます。
テスト用yamlファイル↓
yamlの詳しい解説↓
flutter test の実行を行ってる
https://qiita.com/tokkun5552/items/2eb6793501c152dabf33#%E3%83
%86%E3%82%B9%E3%83%88%E8%87%AA%E5%8B%95%E5%8C%96
https://qiita.com/sensuikan1973/items/0c5efb93e5db54f9d8a2
Codecovやlcovでカバレッジの可視化
・右画像のように、テスト出来ていない
ところが分かる
・やり方は以下
https://qiita.com/tokkun5552/items/2eb6793501c152dabf
33#codecov%E3%81%A7%E3%82%AB%E3%83%90%E3%83
%AC%E3%83%83%E3%82%B8%E5%8F%AF%E8%A6%96%E5
%8C%96
・実際の画面を見てみましょう
まとめ
・単体テストの基本的な書き方と実行の仕方が分かった
・modelから外部処理をRepositoryに分離する方法が分かった
・RepositoryをProviderでDIする方法が分かった
・GitHub Actionsでテストを自動実行する方法が分かった
・Codecovでカバレッジを可視化する方法がわかった
ご清聴ありがとうございました

More Related Content

What's hot

メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろうKota Mizushima
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
Kota Saito
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っている
Koichi Tanaka
 
フロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjugフロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjug
Itsuki Kuroda
 
関数型・オブジェクト指向 宗教戦争に疲れたなたに送るGo言語入門
関数型・オブジェクト指向宗教戦争に疲れたなたに送るGo言語入門関数型・オブジェクト指向宗教戦争に疲れたなたに送るGo言語入門
関数型・オブジェクト指向 宗教戦争に疲れたなたに送るGo言語入門
Tadahiro Ishisaka
 
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。 【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
日本マイクロソフト株式会社
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
shigeki_ohtsu
 
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjug実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
Yahoo!デベロッパーネットワーク
 
Pull Request & TDD 入門
Pull Request & TDD 入門Pull Request & TDD 入門
Pull Request & TDD 入門
ESM SEC
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
大樹 小倉
 
マイクロサービスにおける 非同期アーキテクチャ
マイクロサービスにおける非同期アーキテクチャマイクロサービスにおける非同期アーキテクチャ
マイクロサービスにおける 非同期アーキテクチャ
ota42y
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
masayoshi takahashi
 
事業が対峙する現実からエンジニアリングを俯瞰する #devlove
事業が対峙する現実からエンジニアリングを俯瞰する #devlove事業が対峙する現実からエンジニアリングを俯瞰する #devlove
事業が対峙する現実からエンジニアリングを俯瞰する #devlove
Itsuki Kuroda
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
Takafumi ONAKA
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
Masahito Zembutsu
 
イベント・ソーシングを知る
イベント・ソーシングを知るイベント・ソーシングを知る
イベント・ソーシングを知るShuhei Fujita
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Takuto Wada
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ増田 亨
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
Takuto Wada
 
3週連続DDDその1 ドメイン駆動設計の基本を理解する
3週連続DDDその1  ドメイン駆動設計の基本を理解する3週連続DDDその1  ドメイン駆動設計の基本を理解する
3週連続DDDその1 ドメイン駆動設計の基本を理解する
増田 亨
 

What's hot (20)

メタプログラミングって何だろう
メタプログラミングって何だろうメタプログラミングって何だろう
メタプログラミングって何だろう
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
やはりお前らのMVCは間違っている
やはりお前らのMVCは間違っているやはりお前らのMVCは間違っている
やはりお前らのMVCは間違っている
 
フロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjugフロー効率性とリソース効率性について #xpjug
フロー効率性とリソース効率性について #xpjug
 
関数型・オブジェクト指向 宗教戦争に疲れたなたに送るGo言語入門
関数型・オブジェクト指向宗教戦争に疲れたなたに送るGo言語入門関数型・オブジェクト指向宗教戦争に疲れたなたに送るGo言語入門
関数型・オブジェクト指向 宗教戦争に疲れたなたに送るGo言語入門
 
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。 【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
【BS4】時は来たれり。今こそ .NET 6 へ移行する時。
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
 
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjug実運用して分かったRabbit MQの良いところ・気をつけること #jjug
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
 
Pull Request & TDD 入門
Pull Request & TDD 入門Pull Request & TDD 入門
Pull Request & TDD 入門
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
マイクロサービスにおける 非同期アーキテクチャ
マイクロサービスにおける非同期アーキテクチャマイクロサービスにおける非同期アーキテクチャ
マイクロサービスにおける 非同期アーキテクチャ
 
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
 
事業が対峙する現実からエンジニアリングを俯瞰する #devlove
事業が対峙する現実からエンジニアリングを俯瞰する #devlove事業が対峙する現実からエンジニアリングを俯瞰する #devlove
事業が対峙する現実からエンジニアリングを俯瞰する #devlove
 
エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織エンジニアの個人ブランディングと技術組織
エンジニアの個人ブランディングと技術組織
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
 
イベント・ソーシングを知る
イベント・ソーシングを知るイベント・ソーシングを知る
イベント・ソーシングを知る
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
3週連続DDDその1 ドメイン駆動設計の基本を理解する
3週連続DDDその1  ドメイン駆動設計の基本を理解する3週連続DDDその1  ドメイン駆動設計の基本を理解する
3週連続DDDその1 ドメイン駆動設計の基本を理解する
 

Similar to Flutterで単体テストを行う方法とGitHub Actionsを使った自動化

[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用
[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用
[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用
de:code 2017
 
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
慎一 古賀
 
2015 0227 OSC-Spring Tokyo NETMF
2015 0227 OSC-Spring Tokyo NETMF2015 0227 OSC-Spring Tokyo NETMF
2015 0227 OSC-Spring Tokyo NETMF
Atomu Hidaka
 
.NET Coreとツール類の今
.NET Coreとツール類の今.NET Coreとツール類の今
.NET Coreとツール類の今
Yuki Igarashi
 
新しい Visual Studio & .NET と新時代のアーキテクチャ
新しい Visual Studio & .NET と新時代のアーキテクチャ新しい Visual Studio & .NET と新時代のアーキテクチャ
新しい Visual Studio & .NET と新時代のアーキテクチャ
慎一 古賀
 
MakeGoodで快適なテスト駆動開発を
MakeGoodで快適なテスト駆動開発をMakeGoodで快適なテスト駆動開発を
MakeGoodで快適なテスト駆動開発をAtsuhiro Kubo
 
マイクロサービス開発が捗る Project Tye
マイクロサービス開発が捗る Project Tyeマイクロサービス開発が捗る Project Tye
マイクロサービス開発が捗る Project Tye
Yuta Matsumura
 
.NET 最新ロードマップと今押さえておきたい技術要素
.NET 最新ロードマップと今押さえておきたい技術要素.NET 最新ロードマップと今押さえておきたい技術要素
.NET 最新ロードマップと今押さえておきたい技術要素
Akira Inoue
 
VSCodeで始めるAzure Static Web Apps開発
VSCodeで始めるAzure Static Web Apps開発VSCodeで始めるAzure Static Web Apps開発
VSCodeで始めるAzure Static Web Apps開発
Yuta Matsumura
 
パターンでわかる! .NET Coreの非同期処理
パターンでわかる! .NET Coreの非同期処理パターンでわかる! .NET Coreの非同期処理
パターンでわかる! .NET Coreの非同期処理
Kouji Matsui
 
Azure Machine Learning Build 2020
Azure Machine Learning Build 2020Azure Machine Learning Build 2020
Azure Machine Learning Build 2020
Keita Onabuta
 
2015 1025 OSC-Fall Tokyo NETMF
2015 1025 OSC-Fall Tokyo NETMF2015 1025 OSC-Fall Tokyo NETMF
2015 1025 OSC-Fall Tokyo NETMF
Atomu Hidaka
 
Coderetreat
CoderetreatCoderetreat
Coderetreat
YAMANE Toshiaki
 
.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線
.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線
.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線
Akira Inoue
 
2022年ASP.NETCore2.2~6.0の旅.pptx
2022年ASP.NETCore2.2~6.0の旅.pptx2022年ASP.NETCore2.2~6.0の旅.pptx
2022年ASP.NETCore2.2~6.0の旅.pptx
Masanori Masui
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux
Takayoshi Tanaka
 
Androidテスティング実践3 ユニットテスト・CI編
Androidテスティング実践3 ユニットテスト・CI編Androidテスティング実践3 ユニットテスト・CI編
Androidテスティング実践3 ユニットテスト・CI編
株式会社 NTTテクノクロス
 
【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT
【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT
【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT
cloudconductor
 
2021/03/19 パブリッククラウドを活かす運用プロセス自動化
2021/03/19 パブリッククラウドを活かす運用プロセス自動化2021/03/19 パブリッククラウドを活かす運用プロセス自動化
2021/03/19 パブリッククラウドを活かす運用プロセス自動化
Issei Hiraoka
 
はてなにおける継続的デプロイメントの現状と Docker の導入
はてなにおける継続的デプロイメントの現状と Docker の導入はてなにおける継続的デプロイメントの現状と Docker の導入
はてなにおける継続的デプロイメントの現状と Docker の導入
Yu Nobuoka
 

Similar to Flutterで単体テストを行う方法とGitHub Actionsを使った自動化 (20)

[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用
[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用
[TL04] .NET 15 周年の今こそ考えるクラウドネイティブ アプリケーションと .NET の活用
 
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
運用管理者のための「開発者からみたDevOps」 - Visual Studio 2015 新機能から考える開発者の取り組み
 
2015 0227 OSC-Spring Tokyo NETMF
2015 0227 OSC-Spring Tokyo NETMF2015 0227 OSC-Spring Tokyo NETMF
2015 0227 OSC-Spring Tokyo NETMF
 
.NET Coreとツール類の今
.NET Coreとツール類の今.NET Coreとツール類の今
.NET Coreとツール類の今
 
新しい Visual Studio & .NET と新時代のアーキテクチャ
新しい Visual Studio & .NET と新時代のアーキテクチャ新しい Visual Studio & .NET と新時代のアーキテクチャ
新しい Visual Studio & .NET と新時代のアーキテクチャ
 
MakeGoodで快適なテスト駆動開発を
MakeGoodで快適なテスト駆動開発をMakeGoodで快適なテスト駆動開発を
MakeGoodで快適なテスト駆動開発を
 
マイクロサービス開発が捗る Project Tye
マイクロサービス開発が捗る Project Tyeマイクロサービス開発が捗る Project Tye
マイクロサービス開発が捗る Project Tye
 
.NET 最新ロードマップと今押さえておきたい技術要素
.NET 最新ロードマップと今押さえておきたい技術要素.NET 最新ロードマップと今押さえておきたい技術要素
.NET 最新ロードマップと今押さえておきたい技術要素
 
VSCodeで始めるAzure Static Web Apps開発
VSCodeで始めるAzure Static Web Apps開発VSCodeで始めるAzure Static Web Apps開発
VSCodeで始めるAzure Static Web Apps開発
 
パターンでわかる! .NET Coreの非同期処理
パターンでわかる! .NET Coreの非同期処理パターンでわかる! .NET Coreの非同期処理
パターンでわかる! .NET Coreの非同期処理
 
Azure Machine Learning Build 2020
Azure Machine Learning Build 2020Azure Machine Learning Build 2020
Azure Machine Learning Build 2020
 
2015 1025 OSC-Fall Tokyo NETMF
2015 1025 OSC-Fall Tokyo NETMF2015 1025 OSC-Fall Tokyo NETMF
2015 1025 OSC-Fall Tokyo NETMF
 
Coderetreat
CoderetreatCoderetreat
Coderetreat
 
.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線
.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線
.NET Core と Container, そして Azure Web Apps on Linux による Web アプリ開発最前線
 
2022年ASP.NETCore2.2~6.0の旅.pptx
2022年ASP.NETCore2.2~6.0の旅.pptx2022年ASP.NETCore2.2~6.0の旅.pptx
2022年ASP.NETCore2.2~6.0の旅.pptx
 
20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux20170527 inside .NET Core on Linux
20170527 inside .NET Core on Linux
 
Androidテスティング実践3 ユニットテスト・CI編
Androidテスティング実践3 ユニットテスト・CI編Androidテスティング実践3 ユニットテスト・CI編
Androidテスティング実践3 ユニットテスト・CI編
 
【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT
【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT
【Cloud Week 2015@Hokkaido University】Dockerとインフラ運用自働化とIoT
 
2021/03/19 パブリッククラウドを活かす運用プロセス自動化
2021/03/19 パブリッククラウドを活かす運用プロセス自動化2021/03/19 パブリッククラウドを活かす運用プロセス自動化
2021/03/19 パブリッククラウドを活かす運用プロセス自動化
 
はてなにおける継続的デプロイメントの現状と Docker の導入
はてなにおける継続的デプロイメントの現状と Docker の導入はてなにおける継続的デプロイメントの現状と Docker の導入
はてなにおける継続的デプロイメントの現状と Docker の導入
 

Flutterで単体テストを行う方法とGitHub Actionsを使った自動化