Skip to content

Commit

Permalink
Merge branch 'master' into feature/search-with-result-count
Browse files Browse the repository at this point in the history
  • Loading branch information
LizaShak committed Aug 22, 2019
2 parents 1cbde4d + bbda129 commit 477b485
Show file tree
Hide file tree
Showing 6 changed files with 231 additions and 4 deletions.
78 changes: 78 additions & 0 deletions sdk/search/azure-search-data/src/test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Test Framework

This SDK uses the TestBase core class to record and playback http sessions, to perform integration tests with Search service in Azure.

## Usage

The class: **SearchIndexClientTestBase** is the base test class which other test classes, that need to perform integration tests, must extend it.

These test classes then can use the base client builder, and run the relevant build method.

### Code example

```$java
public class SyncTests extends SearchIndexClientTestBase {
private SearchIndexClient asyncClient;
@Override
void beforeTest() {
super.beforeTest();
asyncClient = builderSetup().indexName("IndexName").buildAsyncClient();
}
@Test
public void indexResultSucceeds() throws Exception {
// initialize indexActions
DocumentIndexResult result = asyncClient.index(new IndexBatch().actions(indexActions)).block();
assert result.results().get(0).statusCode() == 200;
}
}
```

Before running the tests on PLAYBACK mode, you need to run them on RECORD mode to record the http sessions.

### Recording http sessions:

1. Add the following environment variables to your development SDK to be used in JUnit runs:
* AZURE_SERVICE_PRINCIPAL_APP_ID: *The Service Principal application ID*
* AZURE_SERVICE_PRINCIPAL_APP_SECRET: *Service Principal Secret*
* AZURE_DOMAIN_ID: *Azure domain ID*
* AZURE_SUBSCRIPTION_ID: *Azure subscription ID*
* AZURE_TEST_MODE: **RECORD** *for recording* (**PLAYBACK** *for playback mode*)
* INDEX_FILE_NAME: *The json filename where the index configuration is stored (in the resources folder)*

2. Run the tests.

> Please note: In RECORD mode, every test is creating a new testing environment in Azure before the test, and deleting it after the test. This process takes some time, so the tests in this mode (RECORD) are slower.
3. After test runs finish, you can find the recorded sessions under the project's target folder:

`target/test-classes/session-records`

Every test will have its own session file.

4. Copy the records to the project's test resources folder:

`test/resources/session-records`

> The session files should also be submitted to the project's repository, so the tests in the CI build will use them in playback mode.
### Running tests in PLAYBACK mode

To run tests in Playback mode:

1. Set the value of the **AZURE_TEST_MODE** environment variable to *'RECORD'* (or delete it). You can also delete all other environment variables.
2. Run the tests.

## Example of creating test environment in Azure

You can find an example of preparing a test environment in Azure here:

`/test/java/com/azure/search/data/env/samples/CreateTestResources.java`

This example creates a Resource Group and Search Service in Azure, creates a new index and uploads documents to it.

This is for self testing purposes, and shows the usage of the Azure client and Search Service client.

> This is the same process during the Search Tests in RECORDING mode, that creates the test environment before every test, and cleans it after the test ends.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.azure.search.data.generated.models.QueryType.SIMPLE;
import static com.azure.search.data.generated.models.SearchMode.ALL;

public class SearchAsyncTests extends SearchTestBase {

private SearchIndexAsyncClient client;
Expand Down Expand Up @@ -154,7 +157,7 @@ public void orderByProgressivelyBreaksTies() {
PagedFlux<SearchResult> results = client.search("*", new SearchParameters().orderBy(orderByValues), new SearchRequestOptions());
Assert.assertNotNull(results);

List<String> actualResults = results.log().map(res -> (String) res.additionalProperties().get("HotelId")).collectList().block();
List<String> actualResults = results.log().map(res -> getSearchResultId(res, "HotelId")).collectList().block();

Assert.assertArrayEquals(actualResults.toArray(), expectedResults);
}
Expand Down Expand Up @@ -185,6 +188,27 @@ public void canSearchDynamicDocuments() {
Assert.assertTrue(compareResults(actualResults.stream().map(SearchTestBase::dropUnnecessaryFields).collect(Collectors.toList()), hotels));
}

@Override
public void testCanSearchWithSearchModeAll() {
Flux<SearchResult> response = client.search("Cheapest hotel", new SearchParameters().queryType(SIMPLE).searchMode(ALL), new SearchRequestOptions()).log();
StepVerifier.create(response).assertNext(res -> Assert.assertEquals("2", getSearchResultId(res, "HotelId"))).verifyComplete();
}

@Override
public void testDefaultSearchModeIsAny() {
Flux<SearchResult> response = client.search("Cheapest hotel", new SearchParameters(), new SearchRequestOptions()).log();

StepVerifier.create(response)
.assertNext(res -> Assert.assertEquals("2", getSearchResultId(res, "HotelId")))
.assertNext(res -> Assert.assertEquals("10", getSearchResultId(res, "HotelId")))
.assertNext(res -> Assert.assertEquals("3", getSearchResultId(res, "HotelId")))
.assertNext(res -> Assert.assertEquals("4", getSearchResultId(res, "HotelId")))
.assertNext(res -> Assert.assertEquals("5", getSearchResultId(res, "HotelId")))
.assertNext(res -> Assert.assertEquals("1", getSearchResultId(res, "HotelId")))
.assertNext(res -> Assert.assertEquals("9", getSearchResultId(res, "HotelId")))
.verifyComplete();
}

@Override
public void testCanGetResultCountInSearch() {
Flux<PagedResponse<SearchResult>> results = client.search("*", new SearchParameters().includeTotalResultCount(true), new SearchRequestOptions()).byPage();
Expand Down Expand Up @@ -217,7 +241,7 @@ private void assertKeySequenceEqual(PagedFlux<SearchResult> results, List<String

List<String> actualKeys = results.log()
.filter(doc -> doc.additionalProperties().containsKey("HotelId"))
.map(doc -> (String) doc.additionalProperties().get("HotelId"))
.map(doc -> getSearchResultId(doc, "HotelId"))
.collectList()
.block();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import com.azure.search.data.generated.models.SearchRequestOptions;
import com.azure.search.data.generated.models.SearchResult;
import org.junit.Assert;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -26,6 +25,9 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.azure.search.data.generated.models.QueryType.SIMPLE;
import static com.azure.search.data.generated.models.SearchMode.ALL;

public class SearchSyncTests extends SearchTestBase {

private SearchIndexClient client;
Expand Down Expand Up @@ -191,7 +193,23 @@ public void canFilterNonNullableType() throws Exception {
}

@Override
@Test
public void testCanSearchWithSearchModeAll() {
List<Map<String, Object>> response = getSearchResults(client.search("Cheapest hotel", new SearchParameters().queryType(SIMPLE).searchMode(ALL), new SearchRequestOptions()));
Assert.assertEquals(1, response.size());
Assert.assertEquals("2", response.get(0).get("HotelId"));

}

@Override
public void testDefaultSearchModeIsAny() {
List<Map<String, Object>> response = getSearchResults(client.search("Cheapest hotel", new SearchParameters(), new SearchRequestOptions()));
Assert.assertEquals(7, response.size());
Assert.assertEquals(Arrays.asList("2", "10", "3", "4", "5", "1", "9"), response.stream().map(res -> res.get("HotelId").toString()).collect(Collectors.toList()));

}


@Override
public void testCanGetResultCountInSearch() {
PagedIterable<SearchResult> results = client.search("*", new SearchParameters().includeTotalResultCount(true), new SearchRequestOptions());
Assert.assertNotNull(results);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.azure.search.data.generated.models.IndexActionType;
import com.azure.search.data.generated.models.SearchParameters;
import com.azure.search.data.generated.models.SearchRequestOptions;
import com.azure.search.data.generated.models.SearchResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Assert;
import org.junit.Rule;
Expand Down Expand Up @@ -129,6 +130,10 @@ List<Map<String, Object>> prepareDataForNonNullableTest() throws Exception {
Collectors.toList());
}

protected String getSearchResultId(SearchResult searchResult, String idFieldName) {
return searchResult.additionalProperties().get(idFieldName).toString();
}

protected abstract void setIndexName(String indexName);

@Test
Expand Down Expand Up @@ -163,6 +168,12 @@ public void searchThrowsWhenRequestIsMalformed() {
@Test
public abstract void canFilter();

@Test
public abstract void testCanSearchWithSearchModeAll();

@Test
public abstract void testDefaultSearchModeIsAny();

@Test
public abstract void testCanGetResultCountInSearch();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"networkCallRecords" : [ {
"Method" : "POST",
"Uri" : "https://azs-sdk2dd3609540a3.search.windows.net/indexes('hotels')/docs/search.index?api-version=2019-05-06",
"Headers" : {
"Content-Type" : "application/json; charset=utf-8"
},
"Response" : {
"Pragma" : "no-cache",
"retry-after" : "0",
"request-id" : "4569dce8-0dbc-4378-ab47-a1609e8b0e41",
"StatusCode" : "200",
"Date" : "Wed, 21 Aug 2019 13:31:27 GMT",
"Strict-Transport-Security" : "max-age=15724800; includeSubDomains",
"Cache-Control" : "no-cache",
"elapsed-time" : "204",
"OData-Version" : "4.0",
"Expires" : "-1",
"Content-Length" : "795",
"Body" : "{\"@odata.context\":\"https://azs-sdk2dd3609540a3.search.windows.net/indexes('hotels')/$metadata#Collection(Microsoft.Azure.Search.V2019_05_06.IndexResult)\",\"value\":[{\"key\":\"1\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"2\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"3\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"4\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"5\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"6\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"7\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"8\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"9\",\"status\":true,\"errorMessage\":null,\"statusCode\":201},{\"key\":\"10\",\"status\":true,\"errorMessage\":null,\"statusCode\":201}]}",
"Preference-Applied" : "odata.include-annotations=\"*\"",
"Content-Type" : "application/json; odata.metadata=minimal"
}
}, {
"Method" : "POST",
"Uri" : "https://azs-sdk2dd3609540a3.search.windows.net/indexes('hotels')/docs/search.post.search?api-version=2019-05-06",
"Headers" : {
"Content-Type" : "application/json; charset=utf-8"
},
"Response" : {
"Pragma" : "no-cache",
"retry-after" : "0",
"request-id" : "663a4c7c-e95b-46fd-be77-95b4721dac58",
"StatusCode" : "200",
"Date" : "Wed, 21 Aug 2019 13:31:29 GMT",
"Strict-Transport-Security" : "max-age=15724800; includeSubDomains",
"Cache-Control" : "no-cache",
"elapsed-time" : "32",
"OData-Version" : "4.0",
"Expires" : "-1",
"Content-Length" : "605",
"Body" : "{\"@odata.context\":\"https://azs-sdk2dd3609540a3.search.windows.net/indexes('hotels')/$metadata#docs(*)\",\"value\":[{\"@search.score\":0.29120865,\"HotelId\":\"2\",\"HotelName\":\"Roach Motel\",\"Description\":\"Cheapest hotel in town. Infact, a motel.\",\"Description_fr\":\"H\\u00f4tel le moins cher en ville. Infact, un motel.\",\"Category\":\"Budget\",\"Tags\":[\"motel\",\"budget\"],\"ParkingIncluded\":true,\"SmokingAllowed\":true,\"LastRenovationDate\":\"1982-04-28T00:00:00Z\",\"Rating\":1,\"Location\":{\"type\":\"Point\",\"coordinates\":[-122.131577,49.678581],\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}}},\"Address\":null,\"Rooms\":[]}]}",
"Preference-Applied" : "odata.include-annotations=\"*\"",
"Content-Type" : "application/json; odata.metadata=minimal"
}
} ],
"variables" : [ ]
}
Loading

0 comments on commit 477b485

Please sign in to comment.