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


関連記事

laravel logo

[Laravel] ログの扱い方 [5.8]

1 はじめに2 環境3 Monologについて4 コード上で設定する方法5 config/logging.phpで設定する方法6 おまけ:ログレベルについて7 さいごに8 おすすめ書籍 はじめに こん ...

Go言語

Goのfmt.print系関数のまとめ

1 はじめに2 print関数の命名規則3 各print関数の説明3.1 Print(標準出力へ出力)系関数3.2 Sprint(文字列を出力)系関数3.3 Fprint(ファイルへ出力)系関数4 書 ...

Go言語

Go言語で使えるmigrationライブラリ

1 はじめに2 migrationライブラリ2.1 goose2.2 sql-migrate2.3 migu2.4 pop2.5 sqldef3 sqldefを使ってみる3.1 導入3.2 テーブルを ...

Stripe Connectを使ってCheckoutを利用した継続課金を実装

1 はじめに1.1 Checkoutを使う場合の動線2 決済画面への遷移2.1 マイグレーション2.2 Checkout Sessionの作成3 決済完了後の制御4 おまけ4.1 ローカルでWebho ...

Laravelのchunkメソッドとcursorメソッドのメモリ使用量

1 はじめに2 テスト用のデータ準備3 get()4 chunk()5 chunkById()6 cursor()7 さいごに8 おすすめ書籍 はじめに テーブルの全レコードに一括で処理を行うバッチを ...

フォロー

blog-page_side_responsive

2018年10月
 123456
78910111213
14151617181920
21222324252627
28293031  

アプリ情報

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