From bf33378bc4d54169cc671b5eec7ab01d2ac59697 Mon Sep 17 00:00:00 2001 From: shafang Date: Sun, 15 Dec 2019 18:30:35 -0800 Subject: [PATCH 1/2] resolved conflict --- .../TextAnalyticsAsyncClientTest.java | 48 +++++++++++++++ .../TextAnalyticsClientTest.java | 36 +++++++++++ .../TextAnalyticsClientTestBase.java | 59 +++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java index 90b94049c7d7..1157866db52e 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java @@ -10,6 +10,8 @@ import com.azure.ai.textanalytics.models.LinkedEntityResult; import com.azure.ai.textanalytics.models.NamedEntity; import com.azure.ai.textanalytics.models.NamedEntityResult; +import com.azure.ai.textanalytics.models.TextDocumentInput; +import com.azure.ai.textanalytics.models.TextSentimentResult; import com.azure.core.exception.HttpResponseException; import com.azure.core.util.Context; import org.junit.jupiter.api.Test; @@ -352,5 +354,51 @@ public void recognizePiiEntitiesForListLanguageHint() { }); } + // Key Phrases + + + + // Sentiment + @Test + public void analyseSentimentForTextInput() { + DetectedLanguage primaryLanguage = new DetectedLanguage().setName("English").setIso6391Name("en").setScore(1.0); + List expectedLanguageList = new ArrayList<>(Arrays.asList(primaryLanguage)); + StepVerifier.create(client.detectLanguage("This is a test English Text")) + .assertNext(response -> validateDetectedLanguages(expectedLanguageList, response.getDetectedLanguages())) + .verifyComplete(); + + new TextSentimentResult(); + + } + + @Test + public void analyseSentimentForEmptyText() { + + } + + @Test + public void analyseSentimentForFaultyText() { + + } + + @Test + public void analyseSentimentForBatchInput() { + + } + + @Test + public void analyseSentimentForBatchInputShowStatistics() { + + } + + @Test + public void analyseSentimentForBatchStringInput() { + + } + + @Test + public void analyseSentimentForListLanguageHint() { + + } } diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTest.java b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTest.java index 0dcae508f59c..94109480f1c0 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTest.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTest.java @@ -313,4 +313,40 @@ public void recognizeKeyPhrasesForBatchStringInput() { public void recognizeKeyPhrasesForListLanguageHint() { } + + // Sentiment + @Test + public void analyseSentimentForTextInput() { + + } + + @Test + public void analyseSentimentForEmptyText() { + + } + + @Test + public void analyseSentimentForFaultyText() { + + } + + @Test + public void analyseSentimentForBatchInput() { + + } + + @Test + public void analyseSentimentForBatchInputShowStatistics() { + + } + + @Test + public void analyseSentimentForBatchStringInput() { + + } + + @Test + public void analyseSentimentForListLanguageHint() { + + } } diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java index deb8375fe418..cffb75a12994 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java @@ -17,6 +17,7 @@ import com.azure.ai.textanalytics.models.TextBatchStatistics; import com.azure.ai.textanalytics.models.TextDocumentInput; import com.azure.ai.textanalytics.models.TextDocumentStatistics; +import com.azure.ai.textanalytics.models.TextSentiment; import com.azure.core.credential.TokenCredential; import com.azure.core.exception.HttpResponseException; import com.azure.core.http.HttpClient; @@ -61,6 +62,7 @@ public abstract class TextAnalyticsClientTestBase extends TestBase { private static final String NAME = "name"; private static final String VERSION = "version"; private static final String DEFAULT_SCOPE = "https://cognitiveservices.azure.com/.default"; + final Map properties = CoreUtils.getProperties(TEXT_ANALYTICS_PROPERTIES); private final String clientName = properties.getOrDefault(NAME, "UnknownName"); private final String clientVersion = properties.getOrDefault(VERSION, "UnknownVersion"); @@ -445,6 +447,49 @@ static DocumentResultCollection getExpectedBatchLinkedEntiti + // Sentiment + @Test + public abstract void analyseSentimentForTextInput(); + + @Test + public abstract void analyseSentimentForEmptyText(); + + @Test + public abstract void analyseSentimentForFaultyText(); + + @Test + public abstract void analyseSentimentForBatchInput(); + + @Test + public abstract void analyseSentimentForBatchInputShowStatistics(); + + @Test + public abstract void analyseSentimentForBatchStringInput(); + + @Test + public abstract void analyseSentimentForListLanguageHint(); + + static void analyseSentimentLanguageHintRunner(BiConsumer, String> testRunner) { + final List inputs = Arrays.asList( + "The hotel was dark and unclean." + ); + + testRunner.accept(inputs, "en"); + } + + static void analyseSentimentStringInputRunner(Consumer> testRunner) { + final List inputs = Arrays.asList( + "The hotel was dark and unclean.", + "The restaurant had amazing gnocchi." + ); + + testRunner.accept(inputs); + } + + static void analyseBatchSentimentRunner(Consumer> testRunner) { + + } + private TextAnalyticsRequestOptions setTextAnalyticsRequestOptions() { this.showStatistics = true; return new TextAnalyticsRequestOptions().setShowStatistics(true); @@ -717,6 +762,20 @@ static void validateLinkedEntities(List expectedLinkedEntityList, validateLinkedEntity(expectedLinkedEntity, actualLinkedEntity); } } + + /** + * Helper method to validate the list of named entities. + * + * @param expectedSentimentList analyzed sentiment returned by the service. + * @param actualSentimentList analyzed sentiment returned by the API. + */ + static void validAnalyzedSentiment(List expectedSentimentList, + List actualSentimentList) { + + assertEquals(expectedSentimentList.size(), actualSentimentList.size()); + expectedSentimentList.sort(Comparator.comparing(TextSentiment::getTextSentimentClass)); + } + static void assertRestException(Throwable exception, Class expectedExceptionType, int expectedStatusCode) { assertEquals(expectedExceptionType, exception.getClass()); From 9a4973d3ae200de9189a6a83104813cae2d7c293 Mon Sep 17 00:00:00 2001 From: shafang Date: Mon, 16 Dec 2019 08:02:29 -0800 Subject: [PATCH 2/2] sentiment init --- .../TextAnalyticsAsyncClient.java | 9 +- .../textanalytics/models/TextSentiment.java | 6 +- .../models/TextSentimentResult.java | 19 +++ .../batch/AnalyzeSentimentBatchDocuments.java | 17 ++- .../batch/DetectLanguageBatchDocuments.java | 6 +- .../TextAnalyticsAsyncClientTest.java | 24 ++-- .../TextAnalyticsClientTestBase.java | 122 ++++++++++++++++-- 7 files changed, 167 insertions(+), 36 deletions(-) diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClient.java b/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClient.java index e92b1f8ed1e2..5edd9bbf53e7 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClient.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClient.java @@ -944,13 +944,16 @@ private TextSentimentResult convertToTextSentimentResult(final DocumentSentiment return null; } //TODO (shawn): calculate max length - documentSentimentText.setLength("MAX_LENGTH").setOffset(0).setTextSentimentClass(documentSentimentClass); + documentSentimentText.setTextSentimentClass(documentSentimentClass); setTextSentimentScore(documentSentiment.getDocumentScores(), documentSentimentClass, documentSentimentText); // Sentence text sentiment final List sentenceSentimentTexts = convertToSentenceSentiments(documentSentiment.getSentences()); + documentSentimentText.setLength(sentenceSentimentTexts.stream().mapToInt(TextSentiment::getLength).sum()); + documentSentimentText.setOffset(0); + return new TextSentimentResult(documentSentiment.getId(), documentSentiment.getStatistics(), null, documentSentimentText, sentenceSentimentTexts); } @@ -959,8 +962,8 @@ private List convertToSentenceSentiments(final List sentenceSentimentCollection = new ArrayList<>(); sentenceSentiments.stream().forEach(sentenceSentiment -> { final TextSentiment singleSentenceSentiment = new TextSentiment(); - singleSentenceSentiment.setLength(Integer.toString(sentenceSentiment.getLength())); - singleSentenceSentiment.setLength(Integer.toString(sentenceSentiment.getOffset())); + singleSentenceSentiment.setLength(sentenceSentiment.getLength()); + singleSentenceSentiment.setOffset(sentenceSentiment.getOffset()); final TextSentimentClass sentimentClass = convertToTextSentimentClass(sentenceSentiment.getSentiment()); setTextSentimentScore(sentenceSentiment.getSentenceScores(), sentimentClass, singleSentenceSentiment); singleSentenceSentiment.setTextSentimentClass(sentimentClass); diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentiment.java b/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentiment.java index 1977fe697d1c..c9b6728af564 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentiment.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentiment.java @@ -19,18 +19,18 @@ public class TextSentiment { private double positiveScore; // sentence - private String length; + private int length; private int offset; // sentiment string private TextSentimentClass textSentimentClass; - public String getLength() { + public int getLength() { return length; } - public TextSentiment setLength(String length) { + public TextSentiment setLength(int length) { this.length = length; return this; } diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentimentResult.java b/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentimentResult.java index 91cc2ee5a638..eb1323f30042 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentimentResult.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/main/java/com/azure/ai/textanalytics/models/TextSentimentResult.java @@ -16,6 +16,15 @@ public final class TextSentimentResult extends DocumentResult { private final TextSentiment documentSentiment; private final List sentenceSentiments; + /** + * TextSentimentResult model constructor + * + * @param id document id + * @param textDocumentStatistics text document statistics + * @param error the document error + * @param documentSentiment the document sentiment + * @param sentenceSentiments a list of sentence sentiments + */ public TextSentimentResult(String id, TextDocumentStatistics textDocumentStatistics, Error error, TextSentiment documentSentiment, List sentenceSentiments) { super(id, textDocumentStatistics, error); @@ -23,10 +32,20 @@ public TextSentimentResult(String id, TextDocumentStatistics textDocumentStatist this.sentenceSentiments = sentenceSentiments; } + /** + * Get the document sentiment. + * + * @return the document sentiment + */ public TextSentiment getDocumentSentiment() { return documentSentiment; } + /** + * Get a list of sentence sentiments. + * + * @return a list of sentence sentiments + */ public List getSentenceSentiments() { return sentenceSentiments; } diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/AnalyzeSentimentBatchDocuments.java b/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/AnalyzeSentimentBatchDocuments.java index 2cd155ab892d..53c121d66104 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/AnalyzeSentimentBatchDocuments.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/AnalyzeSentimentBatchDocuments.java @@ -11,6 +11,7 @@ import com.azure.ai.textanalytics.models.TextDocumentInput; import com.azure.ai.textanalytics.models.TextSentiment; import com.azure.ai.textanalytics.models.TextSentimentResult; +import com.azure.core.util.Configuration; import com.azure.core.util.Context; import java.util.Arrays; @@ -21,14 +22,16 @@ public class AnalyzeSentimentBatchDocuments { public static void main(String[] args) { // Instantiate a client that will be used to call the service. TextAnalyticsClient client = new TextAnalyticsClientBuilder() - .subscriptionKey("subscription-key") - .endpoint("https://servicename.cognitiveservices.azure.com/") +// .subscriptionKey("subscription-key") +// .endpoint("https://servicename.cognitiveservices.azure.com/") + .subscriptionKey(Configuration.getGlobalConfiguration().get("AZURE_TEXT_ANALYTICS_SUBSCRIPTION_KEY")) + .endpoint(Configuration.getGlobalConfiguration().get("AZURE_TEXT_ANALYTICS_ENDPOINT")) .buildClient(); // The texts that need be analysed. List inputs = Arrays.asList( - new TextDocumentInput("1", "The hotel was dark and unclean.", "en"), - new TextDocumentInput("2", "The restaurant had amazing gnocchi.", "en") + new TextDocumentInput("1", "The hotel was dark and unclean. The restaurant had amazing gnocchi.", "en"), + new TextDocumentInput("2", "The restaurant had amazing gnocchi. The hotel was dark and unclean.", "en") ); final TextAnalyticsRequestOptions requestOptions = new TextAnalyticsRequestOptions().setShowStatistics(true); @@ -60,8 +63,8 @@ public static void main(String[] args) { sentenceSentiment.getNeutralScore(), sentenceSentiment.getNegativeScore(), sentenceSentiment.getLength(), - sentenceSentiment.getOffset()); - } - } + sentenceSentiment.getOffset())); + + }); } } diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/DetectLanguageBatchDocuments.java b/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/DetectLanguageBatchDocuments.java index 3cf61d6d3b3d..049d81f2e1c9 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/DetectLanguageBatchDocuments.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/samples/java/com/azure/ai/textanalytics/batch/DetectLanguageBatchDocuments.java @@ -57,9 +57,9 @@ public static void main(String[] args) { System.out.printf("Other detected Languages: %s, ISO 6391 Name: %s, Score: %s.%n", detectedLanguage.getName(), detectedLanguage.getIso6391Name(), - detectedLanguage.getScore()); - } - } + detectedLanguage.getScore())); + + }); } } diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java index 1157866db52e..3224351fe6d0 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsAsyncClientTest.java @@ -10,8 +10,8 @@ import com.azure.ai.textanalytics.models.LinkedEntityResult; import com.azure.ai.textanalytics.models.NamedEntity; import com.azure.ai.textanalytics.models.NamedEntityResult; -import com.azure.ai.textanalytics.models.TextDocumentInput; -import com.azure.ai.textanalytics.models.TextSentimentResult; +import com.azure.ai.textanalytics.models.TextSentiment; +import com.azure.ai.textanalytics.models.TextSentimentClass; import com.azure.core.exception.HttpResponseException; import com.azure.core.util.Context; import org.junit.jupiter.api.Test; @@ -362,14 +362,20 @@ public void recognizePiiEntitiesForListLanguageHint() { // Sentiment @Test public void analyseSentimentForTextInput() { - DetectedLanguage primaryLanguage = new DetectedLanguage().setName("English").setIso6391Name("en").setScore(1.0); - List expectedLanguageList = new ArrayList<>(Arrays.asList(primaryLanguage)); - StepVerifier.create(client.detectLanguage("This is a test English Text")) - .assertNext(response -> validateDetectedLanguages(expectedLanguageList, response.getDetectedLanguages())) - .verifyComplete(); - - new TextSentimentResult(); + final TextSentiment expectedDocumentSentiment = new TextSentiment() + .setTextSentimentClass(TextSentimentClass.MIXED).setLength(66).setOffset(0); + final List expectedSentiments = Arrays.asList( + new TextSentiment().setTextSentimentClass(TextSentimentClass.NEGATIVE).setLength(31).setOffset(0), + new TextSentiment().setTextSentimentClass(TextSentimentClass.POSITIVE).setLength(35).setOffset(32) + ); + + StepVerifier.create(client.analyzeSentiment("The hotel was dark and unclean. The restaurant had amazing gnocchi.")) + .assertNext(response -> { + validateAnalysedSentiment(expectedDocumentSentiment, response.getDocumentSentiment()); + validateAnalysedSentenceSentiment(expectedSentiments, response.getSentenceSentiments()); + }) + .verifyComplete(); } @Test diff --git a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java index cffb75a12994..baa62a3981e0 100644 --- a/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java +++ b/sdk/textanalytics/azure-ai-textanalytics/src/test/java/com/azure/ai/textanalytics/TextAnalyticsClientTestBase.java @@ -18,6 +18,8 @@ import com.azure.ai.textanalytics.models.TextDocumentInput; import com.azure.ai.textanalytics.models.TextDocumentStatistics; import com.azure.ai.textanalytics.models.TextSentiment; +import com.azure.ai.textanalytics.models.TextSentimentClass; +import com.azure.ai.textanalytics.models.TextSentimentResult; import com.azure.core.credential.TokenCredential; import com.azure.core.exception.HttpResponseException; import com.azure.core.http.HttpClient; @@ -69,8 +71,11 @@ public abstract class TextAnalyticsClientTestBase extends TestBase { private boolean showStatistics = false; private HttpLogOptions httpLogOptions = new HttpLogOptions(); + static final String MODEL_VERSION = "2019-10-01"; + static final int ZERO = 0; + enum TestEndpoint { - LANGUAGE, NAMED_ENTITY, LINKED_ENTITY + LANGUAGE, NAMED_ENTITY, LINKED_ENTITY, SENTIMENT } T clientSetup(Function clientBuilder) { @@ -173,6 +178,7 @@ static void recognizeNamedEntitiesLanguageHintRunner(BiConsumer, St testRunner.accept(inputs, "en"); } + static void detectLanguageStringInputRunner(Consumer> testRunner) { final List inputs = Arrays.asList( "This is written in English", "Este es un document escrito en EspaƱol.", "~@!~:)"); @@ -211,6 +217,7 @@ static void recognizePiiLanguageHintRunner(BiConsumer, String> test testRunner.accept(inputs, "en"); } + static void recognizePiiStringInputRunner(Consumer> testRunner) { final List inputs = Arrays.asList( "Microsoft employee with ssn 859-98-0987 is using our awesome API's.", @@ -257,6 +264,7 @@ static void recognizeLinkedLanguageHintRunner(BiConsumer, String> t testRunner.accept(inputs, "en"); } + static void recognizeLinkedStringInputRunner(Consumer> testRunner) { final List inputs = Arrays.asList( "Microsoft employee with ssn 859-98-0987 is using our awesome API's.", @@ -294,7 +302,7 @@ static DocumentResultCollection getExpectedBatchDetectedLa TextBatchStatistics textBatchStatistics = new TextBatchStatistics().setDocumentCount(3).setErroneousDocumentCount(0).setTransactionCount(3).setValidDocumentCount(3); List detectLanguageResultList = Arrays.asList(detectLanguageResult1, detectLanguageResult2, detectLanguageResult3); - return new DocumentResultCollection<>(detectLanguageResultList, "2019-10-01", textBatchStatistics); + return new DocumentResultCollection<>(detectLanguageResultList, MODEL_VERSION, textBatchStatistics); } static DocumentResultCollection getExpectedBatchNamedEntities() { @@ -314,7 +322,7 @@ static DocumentResultCollection getExpectedBatchNamedEntities TextBatchStatistics textBatchStatistics = new TextBatchStatistics().setDocumentCount(2).setErroneousDocumentCount(0).setTransactionCount(2).setValidDocumentCount(2); List namedEntityResultList = Arrays.asList(namedEntityResult1, namedEntityResult2); - return new DocumentResultCollection<>(namedEntityResultList, "2019-10-01", textBatchStatistics); + return new DocumentResultCollection<>(namedEntityResultList, MODEL_VERSION, textBatchStatistics); } static DocumentResultCollection getExpectedBatchPiiEntities() { @@ -333,7 +341,7 @@ static DocumentResultCollection getExpectedBatchPiiEntities() TextBatchStatistics textBatchStatistics = new TextBatchStatistics().setDocumentCount(2).setErroneousDocumentCount(0).setTransactionCount(2).setValidDocumentCount(2); List namedEntityResultList = Arrays.asList(namedEntityResult1, namedEntityResult2); - return new DocumentResultCollection<>(namedEntityResultList, "2019-10-01", textBatchStatistics); + return new DocumentResultCollection<>(namedEntityResultList, MODEL_VERSION, textBatchStatistics); } static DocumentResultCollection getExpectedBatchLinkedEntities() { @@ -355,7 +363,7 @@ static DocumentResultCollection getExpectedBatchLinkedEntiti TextBatchStatistics textBatchStatistics = new TextBatchStatistics().setDocumentCount(2).setErroneousDocumentCount(0).setTransactionCount(2).setValidDocumentCount(2); List linkedEntityResultList = Arrays.asList(linkedEntityResult1, linkedEntityResult2); - return new DocumentResultCollection<>(linkedEntityResultList, "2019-10-01", textBatchStatistics); + return new DocumentResultCollection<>(linkedEntityResultList, MODEL_VERSION, textBatchStatistics); } // Named Entities @@ -487,7 +495,50 @@ static void analyseSentimentStringInputRunner(Consumer> testRunner) } static void analyseBatchSentimentRunner(Consumer> testRunner) { + final List inputs = Arrays.asList( + new TextDocumentInput("0", "The hotel was dark and unclean."), + new TextDocumentInput("1", "The restaurant had amazing gnocchi.") + ); + + testRunner.accept(inputs); + } + void analyseBatchSentimentShowStatsRunner( + BiConsumer, TextAnalyticsRequestOptions> testRunner) { + final List textDocumentInputs = Arrays.asList( + new TextDocumentInput("0", "The hotel was dark and unclean. The restaurant had amazing gnocchi."), + new TextDocumentInput("1", "The restaurant had amazing gnocchi. The hotel was dark and unclean.") + ); + testRunner.accept(textDocumentInputs, setTextAnalyticsRequestOptions()); + } + + static DocumentResultCollection getExpectedBatchTextSentiment() { + // TODO (shawn): verified character count + final TextDocumentStatistics textDocumentStatistics1 = new TextDocumentStatistics().setCharacterCount(0) + .setTransactionCount(1); + final TextDocumentStatistics textDocumentStatistics2 = new TextDocumentStatistics().setCharacterCount(0) + .setTransactionCount(1); + + final TextSentimentResult textSentimentResult1 = new TextSentimentResult("0", textDocumentStatistics1, + null, + new TextSentiment().setTextSentimentClass(TextSentimentClass.MIXED).setLength(66).setOffset(ZERO), + Arrays.asList( + new TextSentiment().setTextSentimentClass(TextSentimentClass.NEGATIVE).setLength(31).setOffset(0), + new TextSentiment().setTextSentimentClass(TextSentimentClass.POSITIVE).setLength(35).setOffset(31) + )); + + final TextSentimentResult textSentimentResult2 = new TextSentimentResult("1", textDocumentStatistics2, + null, + new TextSentiment().setTextSentimentClass(TextSentimentClass.MIXED).setLength(66).setOffset(ZERO), + Arrays.asList( + new TextSentiment().setTextSentimentClass(TextSentimentClass.POSITIVE).setLength(35).setOffset(0), + new TextSentiment().setTextSentimentClass(TextSentimentClass.NEGATIVE).setLength(31).setOffset(36) + )); + + return new DocumentResultCollection<>(Arrays.asList(textSentimentResult1, textSentimentResult2), + MODEL_VERSION, + new TextBatchStatistics().setDocumentCount(2).setErroneousDocumentCount(0) + .setTransactionCount(2).setValidDocumentCount(2)); } private TextAnalyticsRequestOptions setTextAnalyticsRequestOptions() { @@ -602,6 +653,39 @@ private void validateDocuments(DocumentResultCollection expectedResult, validateNamedEntities(expectedItem.getNamedEntities(), actualItem.getNamedEntities()); } }); + break; + case SENTIMENT: + final List expectedSentimentResults = expectedResult.stream() + .filter(element -> element instanceof TextSentimentResult) + .map(element -> (TextSentimentResult) element) + .collect(Collectors.toList()); + + final List actualSentimentResults = actualResult.stream() + .filter(element -> element instanceof TextSentimentResult) + .map(element -> (TextSentimentResult) element) + .collect(Collectors.toList()); + + expectedSentimentResults.sort(Comparator.comparing(TextSentimentResult::getId)); + actualSentimentResults.sort(Comparator.comparing(TextSentimentResult::getId)); + final int actualSize = actualSentimentResults.size(); + final int expectedSize = expectedSentimentResults.size(); + assertEquals(expectedSize, actualSize); + + for (int i = 0; i < actualSize; i++) { + final TextSentimentResult actualSentimentResult = actualSentimentResults.get(i); + final TextSentimentResult expectedSentimentResult = expectedSentimentResults.get(i); + + if (actualSentimentResult.getError() == null) { + if (this.showStatistics) { + validateDocumentStatistics(expectedSentimentResult.getStatistics(), actualSentimentResult.getStatistics()); + } + validateAnalysedSentiment(expectedSentimentResult.getDocumentSentiment(), actualSentimentResult.getDocumentSentiment()); + validateAnalysedSentenceSentiment(expectedSentimentResult.getSentenceSentiments(), actualSentimentResult.getSentenceSentiments()); + } else { + validateErrorDocument(actualSentimentResult.getError(), actualSentimentResult.getError()); + } + } + break; default: throw new IllegalArgumentException(String.format("Unsupported testApi : '%s'.", testApi)); @@ -764,16 +848,32 @@ static void validateLinkedEntities(List expectedLinkedEntityList, } /** - * Helper method to validate the list of named entities. + * Helper method to validate the list of sentence sentiment. Can't really validate score numbers because it + * frequently changed by background model computation. * - * @param expectedSentimentList analyzed sentiment returned by the service. - * @param actualSentimentList analyzed sentiment returned by the API. + * @param expectedSentimentList a list of analyzed sentence sentiment returned by the service. + * @param actualSentimentList a list of analyzed sentence sentiment returned by the API. */ - static void validAnalyzedSentiment(List expectedSentimentList, - List actualSentimentList) { + static void validateAnalysedSentenceSentiment(List expectedSentimentList, + List actualSentimentList) { assertEquals(expectedSentimentList.size(), actualSentimentList.size()); - expectedSentimentList.sort(Comparator.comparing(TextSentiment::getTextSentimentClass)); + for (int i = 0; i < expectedSentimentList.size(); i++) { + validateAnalysedSentiment(expectedSentimentList.get(i), actualSentimentList.get(i)); + } + } + + /** + * Helper method to validate one pair of analysed sentiments. Can't really validate score numbers because it + * frequently changed by background model computation. + * + * @param expectedSentiment analyzed document sentiment returned by the service. + * @param actualSentiment analyzed document sentiment returned by the API. + */ + static void validateAnalysedSentiment(TextSentiment expectedSentiment, TextSentiment actualSentiment) { + assertEquals(expectedSentiment.getLength(), actualSentiment.getLength()); + assertEquals(expectedSentiment.getOffset(), actualSentiment.getOffset()); + assertEquals(expectedSentiment.getTextSentimentClass(), actualSentiment.getTextSentimentClass()); } static void assertRestException(Throwable exception, Class expectedExceptionType,