REST保証のガイド

REST保証ガイド

1. 前書き

REST保証は、REST APIのテストと検証を簡素化するように設計されており、RubyやGroovyなどの動的言語で使用されるテスト手法の影響を大きく受けています。

ライブラリは、動詞と標準のHTTP操作から始めますが、これらの基本をはるかに超えて、HTTPをしっかりサポートしています。

このガイドでは、explore REST-assuredに移動し、Hamcrestを使用してアサーションを実行します。 Hamcrestにまだ慣れていない場合は、最初にチュートリアルTesting with Hamcrestをブラッシュアップする必要があります。

また、REST保証のより高度な使用例については、他の記事をご覧ください。

それでは、簡単な例を見てみましょう。

2. 簡単なテスト例

始める前に、テストに次の静的インポートがあることを確認しましょう。

io.restassured.RestAssured.*
io.restassured.matcher.RestAssuredMatchers.*
org.hamcrest.Matchers.*

テストをシンプルに保ち、メインAPIに簡単にアクセスできるようにするためにそれが必要になります。

それでは、簡単な例から始めましょう。ゲームのデータを公開する基本的な賭けシステムです。

{
    "id": "390",
    "data": {
        "leagueId": 35,
        "homeTeam": "Norway",
        "visitingTeam": "England",
    },
    "odds": [{
        "price": "1.30",
        "name": "1"
    },
    {
        "price": "5.25",
        "name": "X"
    }]
}

これが、ローカルにデプロイされたAPIをヒットしたときのJSON応答であるとしましょう–http://localhost:8080/events?id=390.

ここで、REST-assuredを使用して、応答JSONのいくつかの興味深い機能を検証しましょう。

@Test
public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() {
   get("/events?id=390").then().statusCode(200).assertThat()
      .body("data.leagueId", equalTo(35));
}

したがって、ここで行ったことは、エンドポイント/events?id=390への呼び出しが、dataオブジェクトのleagueIdが35であるJSON Stringを含む本文で応答することを確認したことです。

もっと興味深い例を見てみましょう。 odds配列に価格1.30および5.25のレコードがあることを確認したいとします。

@Test
public void givenUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect() {
   get("/events?id=390").then().assertThat()
      .body("odds.price", hasItems("1.30", "5.25"));
}

3. RESTで保証されたセットアップ

お気に入りの依存関係ツールがMavenの場合、pom.xmlファイルに次の依存関係を追加します。


    io.rest-assured
    rest-assured
    3.0.0
    test

最新バージョンを入手するには、this linkに従ってください。 REST-assuredは、Hamcrestマッチャーの能力を利用してアサーションを実行するため、その依存関係も含める必要があります。


    org.hamcrest
    hamcrest-all
    1.3

最新バージョンは常にthis linkで入手できます。

4. 匿名JSONルート検証

オブジェクトではなくプリミティブで構成される配列を考えてみましょう。

[1, 2, 3]

これは匿名JSONルートと呼ばれ、有効なJSONデータであるにもかかわらずキーと値のペアがないことを意味します。

このようなシナリオでは、パスとして`$`シンボルまたは空の文字列(“”)を使用して検証を実行できます。 上記のサービスをhttp://localhost:8080/jsonで公開すると仮定すると、REST-assuredを使用して次のように検証できます。

when().get("/json").then().body("$", hasItems(1, 2, 3));

またはこのように:

when().get("/json").then().body("", hasItems(1, 2, 3));

5. フロートとダブルス

RESTサービスをテストするためにREST-assuredを使い始めるとき、JSON応答の浮動小数点数がプリミティブ型float.にマップされることを理解する必要があります。

floatタイプの使用は、Javaの多くのシナリオの場合のように、doubleと互換性がありません。

適切な例は、次の応答です。

{
    "odd": {
        "price": "1.30",
        "ck": 12.2,
        "name": "1"
    }
}

ckの値に対して次のテストを実行していると仮定します。

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2));

このテストは、テストする値が応答の値と等しい場合でも失敗します。 これは、floatではなくdoubleと比較しているためです。

これを機能させるには、次のように、equalToマッチャーメソッドのオペランドをfloatとして明示的に指定する必要があります。

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2f));

6. リクエスト方法の指定

通常、使用するリクエストメソッドに対応するget(),などのメソッドを呼び出すことにより、リクエストを実行します。

さらに、we can also specify the HTTP verb using the request() method

@Test
public void whenRequestGet_thenOK(){
    when().request("GET", "/users/eugenp").then().statusCode(200);
}

上記の例は、get()を直接使用するのと同じです。

同様に、HEADCONNECT、およびOPTIONSリクエストを送信できます。

@Test
public void whenRequestHead_thenOK() {
    when().request("HEAD", "/users/eugenp").then().statusCode(200);
}

POSTリクエストも同様の構文に従い、with() およびbody()メソッドを使用してthe body を指定できます。

したがって、POST requestを送信して新しいOdd を作成するには、次のようにします。

@Test
public void whenRequestedPost_thenCreated() {
    with().body(new Odd(5.25f, 1, 13.1f, "X"))
      .when()
      .request("POST", "/odds/new")
      .then()
      .statusCode(201);
}

body として送信されたOdd オブジェクトは、自動的にJSONに変換されます。 送信したい任意のStringPOSTbody.として渡すこともできます

7. デフォルト値の設定

テスト用に多くのデフォルト値を設定できます。

@Before
public void setup() {
    RestAssured.baseURI = "https://api.github.com";
    RestAssured.port = 443;
}

ここでは、リクエストのベースURIとポートを設定しています。 これらに加えて、ベースパス、ルートパット、および認証も構成できます。

注:以下を使用して、RESTが保証する標準のデフォルトにリセットすることもできます。

RestAssured.reset();

8. 応答時間を測定する

measure the response time using the time() and timeIn() methods of the Response objectの方法を見てみましょう。

@Test
public void whenMeasureResponseTime_thenOK() {
    Response response = RestAssured.get("/users/eugenp");
    long timeInMS = response.time();
    long timeInS = response.timeIn(TimeUnit.SECONDS);

    assertEquals(timeInS, timeInMS/1000);
}

ご了承ください:

  • time()は、ミリ秒単位の応答時間を取得するために使用されます

  • timeIn()は、指定された時間単位で応答時間を取得するために使用されます

8.1. 応答時間を検証する

単純なlongMatcher:を使用して、応答時間をミリ秒単位で検証することもできます。

@Test
public void whenValidateResponseTime_thenSuccess() {
    when().get("/users/eugenp").then().time(lessThan(5000L));
}

別の時間単位で応答時間を検証する場合は、time()マッチャーと2番目のTimeUnitパラメーターを使用します。

@Test
public void whenValidateResponseTimeInSeconds_thenSuccess(){
    when().get("/users/eugenp").then().time(lessThan(5L),TimeUnit.SECONDS);
}

9. XML応答の検証

JSON応答を検証できるだけでなく、XMLも検証できます。

http://localhost:8080/employeesにリクエストを送信し、次の応答を受け取ったとしましょう。


    
        Jane
        Daisy
        f
    

次のように、first-nameJaneであることを確認できます。

@Test
public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() {
    post("/employees").then().assertThat()
      .body("employees.employee.first-name", equalTo("Jane"));
}

また、ボディマッチャーを次のように連結することにより、すべての値が期待値と一致することを確認できます。

@Test
public void givenUrl_whenMultipleXmlValuesTestEqual_thenCorrect() {
    post("/employees").then().assertThat()
      .body("employees.employee.first-name", equalTo("Jane"))
        .body("employees.employee.last-name", equalTo("Daisy"))
          .body("employees.employee.sex", equalTo("f"));
}

または、可変引数付きの簡略版を使用します。

@Test
public void givenUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect() {
    post("/employees")
      .then().assertThat().body("employees.employee.first-name",
        equalTo("Jane"),"employees.employee.last-name",
          equalTo("Daisy"), "employees.employee.sex",
            equalTo("f"));
}

10. XPath for XML

We can also verify our responses using XPath.first-nameでマッチャーを実行する以下の例について考えてみます。

@Test
public void givenUrl_whenValidatesXmlUsingXpath_thenCorrect() {
    post("/employees").then().assertThat().
      body(hasXPath("/employees/employee/first-name", containsString("Ja")));
}

XPathは、equalToマッチャーを実行する別の方法も受け入れます。

@Test
public void givenUrl_whenValidatesXmlUsingXpath2_thenCorrect() {
    post("/employees").then().assertThat()
      .body(hasXPath("/employees/employee/first-name[text()='Jane']"));
}

11. ロギングテストの詳細

11.1. ログリクエストの詳細

まず、log entire request details using*log().all()*:の方法を見てみましょう

@Test
public void whenLogRequest_thenOK() {
    given().log().all()
      .when().get("/users/eugenp")
      .then().statusCode(200);
}

これにより、次のようなログが記録されます。

Request method:  GET
Request URI:    https://api.github.com:443/users/eugenp
Proxy:          
Request params: 
Query params:   
Form params:    
Path params:    
Multiparts:     
Headers:        Accept=*/*
Cookies:        
Body:           

リクエストの特定の部分のみをログに記録するために、params(), body(), headers(), cookies(), method(), path()と組み合わせたlog()メソッドがあります(例:log.().params().

使用される他のライブラリまたはフィルタは、サーバーに実際に送信されるものを変更する可能性があるため、これは最初のリクエスト仕様をログに記録するためにのみ使用する必要があることに注意してください。

11.2. ログ応答の詳細

同様に、応答の詳細を記録できます。

次の例では、応答本文のみをログに記録しています。

@Test
public void whenLogResponse_thenOK() {
    when().get("/repos/eugenp/tutorials")
      .then().log().body().statusCode(200);
}

出力例:

{
    "id": 9754983,
    "name": "tutorials",
    "full_name": "eugenp/tutorials",
    "private": false,
    "html_url": "https://github.com/eugenp/tutorials",
    "description": "The \"REST With Spring\" Course: ",
    "fork": false,
    "size": 72371,
    "license": {
        "key": "mit",
        "name": "MIT License",
        "spdx_id": "MIT",
        "url": "https://api.github.com/licenses/mit"
    },
...
}

11.3. 状態が発生した場合のログ応答

エラーが発生した場合、またはステータスコードが指定された値と一致した場合にのみ応答を記録するオプションもあります。

@Test
public void whenLogResponseIfErrorOccurred_thenSuccess() {

    when().get("/users/eugenp")
      .then().log().ifError();
    when().get("/users/eugenp")
      .then().log().ifStatusCodeIsEqualTo(500);
    when().get("/users/eugenp")
      .then().log().ifStatusCodeMatches(greaterThan(200));
}

11.4. 検証に失敗した場合はログに記録する

検証に失敗した場合にのみ、リクエストとレスポンスの両方を記録することもできます。

@Test
public void whenLogOnlyIfValidationFailed_thenSuccess() {
    when().get("/users/eugenp")
      .then().log().ifValidationFails().statusCode(200);

    given().log().ifValidationFails()
      .when().get("/users/eugenp")
      .then().statusCode(200);
}

この例では、ステータスコードが200であることを検証します。 これが失敗した場合にのみ、要求と応答がログに記録されます。

12. 結論

このチュートリアルでは、explored the REST-assured frameworkを使用して、RESTfulサービスをテストし、それらの応答を検証するために使用できる最も重要な機能を確認しました。

これらすべての例とコードスニペットの完全な実装は、RESTで保証されたGitHub projectにあります。