BackEnd

Go言語でGinkgoを利用してBDDしてみた

投稿日:2018年10月29日 更新日:

はじめに

こんにちはsuzukiです。Go言語の連載9回目です。
今回はライブラリのGinkgoを利用してBDDについて説明いたします。

BDDとは

BDD(BehaviorDrivenDevelopment)とはビヘイビア駆動開発と呼ばれる開発方法です。

  • 実現したい機能の振る舞い(要求仕様)を決める
  • 振る舞い(要求仕様)を元にテストコードを作成
  • テストコードを満たすための機能を開発
  • リファクタリングを行う

上記のように開発していきます。

振る舞いの意味については色々な意見があるかと思いますが、この記事では要求仕様として進めさせていただきます。

Ginkgoについて

今回使用するGinkgoについて主要な関数についてまとめさせていただきます。

Ginkgoの概要

BDDを進める上でテストコードの作成を行いやすくするためのライブラリです。
GomegaというMatcherのライブラリと併用して使うことでより自然言語でテストが書きやすくなります。GinkgoにはGomegaと依存関係はないですが、本家のサイトでは使われているので今回こちらも使用していきます。
Ginkgoは簡単にテストスイートの作成とテストスペックのテンプレートの作成が行えます。

Describe

テストスペックを作成すると元から入っている関数です。こちらのテキスト部分でテストの対象が何かを記述します。
こちらの中に要求仕様をまとめて記述を行ったりBeforeEachなどの関数をネストできます。

Context

こちらも機能的にはDescribeと同様ですが、特定の条件が何かを記述します。例えばユーザーの状態等をここで定義します。

It

こちらのItの中でテスト対象のアウトプットが何かを記述します。テストの対象が実際にどのような動きをしてほしいかなど。
同期で実行されるため、非同期の場合のテストを行う場合はDoneを利用します。

JustBeforeEach

BeforeEachブロックがすべて実行され、Itブロックが実行される直前に実行されます。 この事実を利用してBookの仕様を整理することができます。

BeforeEach

BeforeEachブロックはItブロックの前に実行されます。
ネストされたDescribeブロックとContextブロックで複数のBeforeEachブロックが定義されている場合、最も外側のBeforeEachブロックが最初に実行されます。

AfterEach

AfterEachブロックはItブロックの後に実行されます。
ネストされたDescribeブロックとContextブロックで複数のBeforeEachブロックが定義されている場合、最も外側のBeforeEachブロックが最初に実行されます。

BeforeSuite

BeforeSuiteブロックは、テストスペックが実行される前に一度だけ実行されます。
並列で複数のテストスペック実行する場合、各並列ノードプロセスはBeforeSuiteを呼び出します。

AfterSuite

AfterSuiteブロックは、テストスペックが成功したか失敗したかにかかわらず、すべての実行後に実行されます。 さらに、Ginkgoが割り込み信号(^ C)を受信すると、終了する前にAfterSuiteを実行しようとします。

Gomegaについて

GomegaライブラリはBDD向けのアサーションを提供してくれます。簡単にですが説明させていただきます。

Gomegaの概要

BDDを進める上でIt内のアサーションをわかりやすく作成することができます。
Testifyのアサーションに比べ、BDDを行いやすくするように直感的にわかりやすいアサーションが多くあります。
基本的に (ACTUAL).Should(アサーション(EXPECTED))という形で使われます。

Equal(EXPECTED)

ACTUALとEXPECTEDが等しいか比較を行います。
厳密な比較を行い、対象の型が同じかも比較されます。

BeEquivalentTo

Equal同様にACTUALとEXPECTEDが等しいか比較を行います。
違いとしては比較を行う前に、ACTUALの型をEXPECTEDの型に変換します。
したがって型自体の違いはあまり意識しません。

BeNil()

ACTUALがnilであるかを比較します。
Equalでnilを比較するとエラーになるためnilを比較する場合にはこちらを利用します。

BeZero()

ACTUALが0であるかを比較します。nilの場合も0として扱われ成功します。

ContainSubstring(STRING, ARGS…)

ACTUALに生成された部分文字列が含まれている場合は成功します。

ContainElement(ELEMENT)

ACTUALにELEMENTと等しい要素が含まれていると成功します。 ACTUALは配列、スライス、またはマップでなければなりません。それ以外はエラーです。 マップの場合、ContainElementはマップの値を検索します(キーではありません)。

BDDを試してみる

それでは実際にテストを作成していきます。

GinkGo導入方法

go get コマンドでライブラリの導入可能です。
Gomegaも合わせて取得しましょう。

テストスイート作成

Ginkgoのテストスイート作成機能を利用してテストスイートを作成します。

こちらのコマンドでディレクトリ名_suite_test.goというテストスイートが作成されます。
今回は/Triangleというディレクトリに下記のファイルが作成されました。

こちらでテストスイートの作成ができました。

スペックテンプレート作成

Ginkgoのテストスペック作成機能を利用してテストスペックのテンプレートを作成します。

triangleは開発を行う機能名に置き換えてください。
こちらのコマンドで下記のファイルが作成されました。

スペック作成

こちらの var _ = Describe("Triangle", func() { } の中にスペックの内容を記述します。
今回の仕様がtriangleが面積の計算を行った時に

  • 底辺と高さが正の整数であるときに、面積を計算すると、底辺*高さ/2になる
  • 底辺か高さが負の整数であるときに、面積を計算すると、0になる
  • 底辺か高さが0であるときに、面積を計算すると、0になる

という要求仕様があるとした時に下記のように記述できます。
今回はアサーションを複数書いていますが、意味は一緒です。

Triangleの実装

今回の記事では詳細に触れる必要はあまりないと思っていますが、
前回の記事で作成を行ったトライアングルを元に下記のように実装しました。

Testの実行

Ginkgoのテストコマンドはginkgoです。こちらでテストの実行を行うことができます。

テスト失敗

個人的にBDDのメリットはテストの失敗した時の内容がとても便利だと思っております。
今回はわざとテストを失敗させました。
要求仕様のうちどれだけの機能が実装できていないかが簡単にわかります。

テスト成功

こちらは成功したパターンです。

今回こちらでテストが通過しました。
この後リファクタリングを行い開発が完了します。

今回のテストでは小規模な開発のため、テストを一回行っただけです。
大規模な開発であれば、テストを行うことで進捗率の確認であったり、既存の機能にデグレが発生していないかなどもこまめに確認が取れます。

さいごに

いかがでしたしょうか、私はプログラミングの進捗を報告することがよくあります。
まとめるために時間がかかったり、正確に伝わらなかったりするとストレスを感じるのですが、BDDでは進めたら納得しやすい値を簡単に出せそうだなと思いました。

おすすめ書籍

スターティングGo言語 (CodeZine BOOKS) Goプログラミング実践入門 標準ライブラリでゼロからWebアプリを作る impress top gearシリーズ みんなのGo言語[現場で使える実践テクニック] Go言語でつくるインタプリタ

blog-page_footer_336




blog-page_footer_336




-BackEnd
-,

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

WebアプリからLINEのメッセージを送る方法

1 はじめに2 Messaging APIとは2.1 Messaging APIの仕組み2.2 Webhookイベント2.3 メッセージオブジェクトの種類2.4 料金形態3 LINE Develope ...

rails

Railsのバリデーション

1 はじめに2 基本的なバリデーション3 EachValidatorクラス4 Validatorクラス5 autoload_pathsの編集6 さいごに はじめに 今回はRailsのActiveRec ...

aws

Amazon ECSのタスク定義について

1 はじめに1.1 Amazon ECSのタスク定義についておさらい2 タスク定義3 アプリケーションのアーキテクチャ3.1 Fargate起動タイプ3.2 EC2起動タイプ4 タスク定義パラメータ4 ...

laravel logo

Laravelでの署名付きURL生成

1 はじめに2 今回のサンプル3 ビュー4 ルーティング5 コントローラー5.1 署名付きURLの生成5.2 期限ありの署名付きURLの生成5.3 署名のチェック6 おまけ6.1 署名の仕組7 さいご ...

js

TypeScriptでJavaScriptのライブラリを使用するには?

1 はじめに2 対応方法2.1 npmで@typesからインストールする2.2 自分で型定義ファイルを作る3 Declaration Space3.1 Type Declaration Space3. ...

フォロー

blog-page_side_responsive

2018年10月
 123456
78910111213
14151617181920
21222324252627
28293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。