web-dev-qa-db-ja.com

CRUDのBDDを行う方法は?

Behavior-Driven Development(BDD) をビルドに適用する方法 [〜#〜] crud [〜#〜] アプリケーションを理解したい。

私は主題について多くを読みましたが、私はそれをどのように適用することになっているのか分かりません。私は例で最もよく学ぶので、ミニCRUDアプリケーションを作成しました。誰かにテストを追加して完成させたいと思います。申し込みは簡単な登録フォームです。ユーザーはフォームに自分の電子メールを入力し、サーバーはそれをデータベースに保存します。

Q1。テストすべき動作は何ですか?

Q2。どの部分をテストすればよいですか?

明らかに、ユーザーが自分のメールを登録できるようにしたい。それで、私がテストすることになっている行動ですか?また、UIをテストしますか?登録後、メールが本当にデータベースにあることをテストしますか?そして、どうすればすべてをテストできますか?

https://jsfiddle.net/cufxn40o/26/

Html

<h1>Registration Form</h1>
Email
<input type="text" id="email" />
<button type="button" onclick="client.register();">
  Register
</button>
<div id="error"></div>

Javascript

/**
 * The client represents the code that runs in the browser
 */
var client = {
    register: function () {
    var email = document.getElementById('email').value;
    ajaxPost(server.register, {email: email}, function(result){
        if(result.error){
        document.getElementById('error').innerHTML = result.error;
      } else {
        document.getElementById('error').innerHTML = '';
        alert('Registration successful!');
      }
    });
  }
};

/**
 * The server represents the code that runs on the server
 */
var server = {
    /**
   * The only method the client can call
   */ 
    register: function (model) {
    var error = server.validate(model);
    if(error) return {error: error};
    else
    {
        server.saveRegistration(model.email);
      return {success: true};
    }
  },

  validate:  function (model) {
    if(!model.email) return 'An email is required';
    if(!framework.isValidEmail(model.email)) return 'This is not a valid email';
    if(server.emailExists(model.email)) return 'This email already exist';
  },

  emailExists: function(email){
    return SqlDatabase.some(x => x === email);
  },

  saveRegistration: function(email){
    SqlDatabase.Push(email);
  }
};

/**
 * This is a real SQL database!
 */ 
var SqlDatabase = [];


/**
 * THe framework used by the server code.
 * This code was not created by me
 */ 
var framework = {
    isValidEmail: function(email) {
    return email && email.indexOf('@') !== -1;
  }
};

/**
 * A utility function to simulate an ajax request in this example
 * You can ignore it
 */
function ajaxPost(url, data, callback){
    var result = url(data);
  callback(result);
}
3
Gudradain

ミニCRUDアプリケーションを作成しました。誰かにテストを追加して完成させたいです

BDDを実行している場合は、必要な動作firstを定義しておく必要があります。次にテストを記述し、アプリを構築しました。

SOの動作はおそらく次のようになります。

When a user is on the register page
and types their email in the email field
and presses the register button
then the email should be saved to the database

次に、各行をWebドライバーなどで自動化し、すべてをまとめてテストに入れ、BDDフレームワーク(Cucumber?)で実行します。これにより、ページが読み込まれ、電子メールが入力され、ボタンをクリックして、データベースのエントリがチェックされます。存在する場合、テストは合格です。

今、あなたはあなたのウェブページを書くことができます。機能を追加すると、動作の各行が緑色に変わります。

アプリが完了すると、すべてのテストが緑色になります。

このアプローチの想定される利点は、.

  1. 行動は「平易な英語」で書かれているので、顧客はテストを書くことができます。
  2. テストが実際のアプリに対して実行されているため、緑になると、ユニットではなくUIが表示されます。アプリは、お客様が作成した仕様と一致するため、バグを修正することは不可能です!??
  3. テストの各ステップが赤または緑に変わるので、常に完了する前に実行する必要のある作業量がわかります。

明らかにそこにはいくつかの欠陥があります。このアプローチは、UIテストの「平易な英語」の複数行のテスト記述に要約されます。

これは悪いことではありませんが、他のアプローチと大幅に異なることもありません。

7
Ewan

必要条件

通常、コードを記述する前に動作を定義します。これらは、ややあいまいな高レベルの要件として始まります。

  • 未登録のユーザーは登録できるはずです
  • 登録ユーザーはログインできるはずです
  • 登録ユーザーは自分のパスワードを回復できる必要があります
  • xがログインに失敗した後、登録されたユーザーアカウントをロックする必要があります
  • 未登録のユーザーは、パスワードの回復を使用して他人のパスワードを盗むことができないようにする必要があります
  • 登録済みのユーザーがログインを使用するときは、自分が所有するオブジェクトへのアクセスを許可する必要があります

行動

これらの要件から、非常に具体的な動作を定義できます。各要件は、1つまたは複数の動作として実装されることになります。

たとえば、Webアプリを構築している場合、最初の箇条書きは次の具体的な動作を引き起こす可能性があります。

  • 未登録でサイトにアクセスすると、登録できるリンクが表示されます
  • 「登録」リンクをクリックすると、登録フォームが表示されます
  • フォームに有効な情報を入力すると、アカウントが作成されます
  • 登録フォームにいるときは、カスタマーサポートに連絡して支援を求める方法があるはずです。

テストシナリオ

これらの動作は、テストフレームワークで特定のシナリオに洗練することができます。例えば:

Given I am an unregistered user
When I go to the home page
Then I am presented with a link to the registration page
So that I can become a registered user

作成する正確なシナリオは、フロントエンドによって異なる場合があります。たとえば、視覚障害のあるユーザー、モバイルユーザー、デスクトップユーザー、Webユーザー、APIユーザーなどのシナリオが異なる場合があります。

概要

「未登録のユーザーは登録できるはずです」などのあいまいな要件から始め、特定のユーザーに関連付けられた動作(「ランディングページに移動すると、登録へのリンクが表示されるはずです」)に絞り込み、そこから異なるデバイスなどの特定のテストシナリオを生成します。1つの要件に対して複数の動作があり、すべての動作に対して複数のテストシナリオがある場合があります。

5
Bryan Oakley

ここでは2つの異なる質問があると思います。 1つは、BDDをCRUDアプリに適用する方法、2つ目は、BDDを使用して簡単な登録アプリを作成する方法です。

  1. BDDは特定のコンテキストに適しておらず、その1つは純粋なCRUDアプリを構築しています。その性質上、CRUDには4つの明確に定義された操作(指定されたお客様のデータに対して)があり、これらは通常かなり簡単です。複雑な動作や特別なドメイン言語はありません。したがって、徹底的に学習したい場合は、単純な古いTDDを使用するか、信頼できる単純なCRUDライブラリを使用してください。

  2. 登録アプリは、たとえ単純なものであっても、必ずしもCRUDアプリであるとは限りません(それをCRUDアプリと考えることから始めると、より効果的に抽象化する機能が制限される可能性があります)。ほとんどの場合(ビジネスに応じて)ドメイン言語(顧客、メンバー、登録、制限など)があり、これらのドメインの概念はアプリコードに変換され、複雑な動作をする可能性があります。

この時点で、開発BDDを推進するための方法論であるだけでなく、要件分析の一形態であることを覚えておくことは重要です。ユーザーが経験できるさまざまなシナリオを書き出すことにより、行動を説明する言語も(多くの場合、利害関係者と一緒に)開発します。

たとえば、システムユーザーはメンバー(ライブラリメンバーなど)と呼ばれる場合があり、ユーザーが取るアクションはビジネスによって "登録"と呼ばれる場合があり、 "サインアップ"と呼ばれる場合があります-この言語は重要ですに意見が一致した。アプリの動作を最初に探索する方法はいくつかあります(「ディスカバリー」とも呼ばれます)。私が使用した最も効果的な方法は、「イベントストーミング」の後に「マッピングの例」です。前者はコマンドとイベントのタイムラインを提供し、後者は正確な使用例です。

つまり、Given/When/Thenから始めずに、タイムラインを描画します。メンバーが登録後24時間まで本を借りることができないというルールがあるとします。このように明確にできるルール

タイムライン:

  • イベント:Jon Registered at 14:00 24/10/2018
  • コマンド:ジョンは本「x」を13:00に借りようとします25/10/2018
  • (システムロジック:貸し出し可能-いいえ)
  • 結果/イベント:ジョンはまだ借りることはできないと言った

代替タイムライン:

  • イベント:Jonが2018年10月24日13:00に登録
  • コマンド:ジョンは本「x」を13:00 2018年10月25日13:00に借ります
  • (システムロジック:貸し出し可能-はい)
  • 結果/イベント:ブック "x"がJonに貸与されました
  • コマンド:Jon return book "x" at 13:00 26/10/2018
  • (システムロジック:本が破損していますか?はい)
  • 結果/イベント:本は修理のために「x」リストされました26/10/2018
  • 結果/コマンド:チャージジョン£5

これで、タイムラインのスライスを取得して、Given/When/Then形式を解析するツールで自動化のためにそれらを書き込むことができます。イベントは「ギブンズ」になり、コマンドは「時」になり、アウトカムイベントは「時」になります。代替タイムラインの最初のタイムラインと2番目の部分を見てみましょう。

Scenario: Not allowed to borrow a book - registration less than 24 hrs ago
    Given Jon Registered at 14:00 24/10/2018 
    When Jon tries to borrow book "x" at 13:00 25/10/2018   
    Then Jon should be told they cannot borrow any books yet

Scenario: allowed to borrow a book - registration more than 24 hrs ago
    Given Jon Registered at 13:00 24/10/2018 
    When Jon tries to borrow book "x" at 13:01 25/10/2018 
    Then book "x" should have been loaned to Jon at 13:01 25/10/2018 

Background:
    Given Jon Registered at 13:00 24/10/2018 

Scenario: Being charged for returning a book damaged and listing for repair
    Given Book "x" was loaned to Jon on 13:00 25/10/2018
    When Jon returns the book "x" at 13:00 26/10/2018   
    Then Book "x" should have been listed for repair at 13:05 26/10/2018
    And Jon should have been a £5 damage fee

ここから、これらの「シナリオ」を自動化する必要があります。 Givenステップは、Jonがすでに本を貸し出されている状態でシステムをセットアップします(例:データベース内?)、Whenステップはコマンド(例:API?Webフォーム)を実行します?ブラウザを自動化する必要がある場合があります)。 Thenステップは、その結果、本が修理のためにリストされた(たとえば、データベースが再度ですか?またはメッセージキュー?)こと、およびメンバーに罰金が課されたことを確認します。ここでもアサートしたいメンバーへのフィードバックがあり、ブラウザからの読み取りも含まれる場合があります)。このシナリオが最初に失敗するTDDのようなアプローチに従います(ビジネスロジックがプログラムされていないため)。

3
Jon Acker

上記の価値ある回答に加えて、CURD、または実際にはあらゆる種類のソフトウェアのBDDテストを作成する場合は、ポジティブテストとネガティブテストの両方を作成することを検討してください。

これは、 @ Bryan OaKley で記述された陽性テストの例です。

Given I am an unregistered user
When I go to the home page
Then I am presented with a link to the registration page
So that I can become a registered user

そして、ここに否定的なテストの例があります:

Given I am registered but not an authenticated user
When I try to register myself with the same email I have registered with
I should get an error message that I am already registered

Given I am an authenticated user
When I go to the home page
I shouldn not be presented with a link to the registration page

0
Ehsan