Skip to content

Commit 8cc6db7

Browse files
authored
Add integration, serialization and option-related tests for Translate (#1181)
- Change TranslateOptions to read API key from GOOGLE_API_KEY env variable - Add RemoteTranslateHelper class and related javadoc - Add SerializationTest class to test that objects can be serialized - Add TranslateTest to test vararg options - Add ITTranslateTest to run ntegration tests
1 parent 51f07ff commit 8cc6db7

File tree

9 files changed

+418
-25
lines changed

9 files changed

+418
-25
lines changed

TESTING.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,5 +270,25 @@ Here is an example that clears the bucket created in Step 3 with a timeout of 5
270270
RemoteStorageHelper.forceDelete(storage, bucket, 5, TimeUnit.SECONDS);
271271
```
272272

273+
### Testing code that uses Translate
274+
275+
`RemoteTranslateHelper` contains convenience methods to make is easier to run tests against the
276+
Google Translate service.
277+
278+
1. Create a test Google Cloud project.
279+
280+
2. Follow [Translate Quickstart](https://cloud.google.com/translate/v2/quickstart) to get an API
281+
key.
282+
283+
3. Create a `RemoteTranslateHelper` object using your project ID and API key. Here is an example
284+
that uses the `RemoteTranslateHelper` to list supported languages.
285+
```java
286+
RemoteTranslateHelper translateHelper = RemoteTranslateHelper.create(PROJECT_ID, API_KEY);
287+
Translate translate = translateHelper.options().service();
288+
List<Language> languages = translate.listSupportedLanguages();
289+
```
290+
291+
4. Run your tests.
292+
273293
[cloud-platform-storage-authentication]:https://cloud.google.com/storage/docs/authentication?hl=en#service_accounts
274294
[create-service-account]:https://developers.google.com/identity/protocols/OAuth2ServiceAccount#creatinganaccount

gcloud-java-examples/src/main/java/com/google/cloud/examples/translate/TranslateExample.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,27 +169,32 @@ private static void printUsage() {
169169
actionAndParams.append(' ').append(param);
170170
}
171171
}
172-
System.out.printf("Usage: %s <apiKey> [<targetLanguage>] operation <args>*%s%n",
172+
System.out.printf("Usage: %s [<apiKey>] [<targetLanguage>] operation <args>*%s%n",
173173
TranslateExample.class.getSimpleName(), actionAndParams);
174174
}
175175

176176
@SuppressWarnings("unchecked")
177177
public static void main(String... args) throws Exception {
178-
if (args.length < 2) {
179-
System.out.println("Missing required api key and action");
178+
if (args.length < 1) {
179+
System.out.println("Missing required action");
180180
printUsage();
181181
return;
182182
}
183-
TranslateOptions.Builder optionsBuilder = TranslateOptions.builder(args[0]);
183+
TranslateOptions.Builder optionsBuilder = TranslateOptions.builder();
184184
TranslateAction action;
185185
String actionName;
186186
if (args.length >= 3 && !ACTIONS.containsKey(args[1])) {
187+
optionsBuilder.apiKey(args[0]);
187188
actionName = args[2];
188189
optionsBuilder.targetLanguage(args[1]);
189190
args = Arrays.copyOfRange(args, 3, args.length);
190-
} else {
191+
} else if (args.length >= 2 && !ACTIONS.containsKey(args[0])) {
192+
optionsBuilder.apiKey(args[0]);
191193
actionName = args[1];
192194
args = Arrays.copyOfRange(args, 2, args.length);
195+
} else {
196+
actionName = args[0];
197+
args = Arrays.copyOfRange(args, 1, args.length);
193198
}
194199
action = ACTIONS.get(actionName);
195200
if (action == null) {

gcloud-java-translate/src/main/java/com/google/cloud/translate/TranslateOptions.java

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.cloud.translate;
1818

1919
import static com.google.common.base.MoreObjects.firstNonNull;
20+
import static com.google.common.base.Preconditions.checkArgument;
2021

2122
import com.google.cloud.AuthCredentials;
2223
import com.google.cloud.HttpServiceOptions;
@@ -34,6 +35,7 @@ public class TranslateOptions extends
3435
HttpServiceOptions<Translate, TranslateRpc, TranslateOptions> {
3536

3637
private static final long serialVersionUID = 5997441123713672886L;
38+
private static final String API_KEY_ENV_NAME = "GOOGLE_API_KEY";
3739
private static final Set<String> SCOPES = ImmutableSet.of();
3840

3941
private final String apiKey;
@@ -62,12 +64,10 @@ public TranslateRpc create(TranslateOptions options) {
6264
public static class Builder extends
6365
HttpServiceOptions.Builder<Translate, TranslateRpc, TranslateOptions, Builder> {
6466

65-
private final String apiKey;
67+
private String apiKey;
6668
private String targetLanguage;
6769

68-
private Builder(String apiKey) {
69-
this.apiKey = apiKey;
70-
}
70+
private Builder() {}
7171

7272
private Builder(TranslateOptions options) {
7373
super(options);
@@ -96,6 +96,16 @@ public Builder authCredentials(AuthCredentials authCredentials) {
9696
return self();
9797
}
9898

99+
/**
100+
* Sets the API key used to issue requets. If not set, the API key is looked for in the
101+
* {@code GOOGLE_API_KEY} environment variable. For instructions on how to get an API key see
102+
* <a href="https://cloud.google.com/translate/v2/quickstart">Translate quickstart</a>.
103+
*/
104+
public Builder apiKey(String apiKey) {
105+
this.apiKey = apiKey;
106+
return this;
107+
}
108+
99109
/**
100110
* Sets the code for the default target language. If not set, english ({@code en}) is used.
101111
* {@link Translate#translate(List, TranslateOption...)} and
@@ -112,13 +122,18 @@ public Builder targetLanguage(String targetLanguage) {
112122

113123
@Override
114124
public TranslateOptions build() {
125+
// Auth credentials are not used by Translate
126+
authCredentials(AuthCredentials.noAuth());
115127
return new TranslateOptions(this);
116128
}
117129
}
118130

119131
private TranslateOptions(Builder builder) {
120132
super(TranslateFactory.class, TranslateRpcFactory.class, builder);
121-
this.apiKey = builder.apiKey;
133+
this.apiKey = builder.apiKey != null ? builder.apiKey : defaultApiKey();
134+
checkArgument(this.apiKey != null,
135+
"An API key is required for this service but could not be determined from the builder "
136+
+ "or the environment. Please set an API key using the builder.");
122137
this.targetLanguage = firstNonNull(builder.targetLanguage, Locale.ENGLISH.getLanguage());
123138
}
124139

@@ -142,6 +157,10 @@ protected Set<String> scopes() {
142157
return SCOPES;
143158
}
144159

160+
protected String defaultApiKey() {
161+
return System.getProperty(API_KEY_ENV_NAME, System.getenv(API_KEY_ENV_NAME));
162+
}
163+
145164
/**
146165
* Returns the API key, to be used used to send requests.
147166
*/
@@ -156,15 +175,6 @@ public String targetLanguage() {
156175
return targetLanguage;
157176
}
158177

159-
/**
160-
* Returns a default {@code TranslateOptions} instance given an API key. For instructions on
161-
* how to get an API key see <a href="https://cloud.google.com/translate/v2/quickstart">Translate
162-
* quickstart</a>.
163-
*/
164-
public static TranslateOptions defaultInstance(String apiKey) {
165-
return builder(apiKey).build();
166-
}
167-
168178
@SuppressWarnings("unchecked")
169179
@Override
170180
public Builder toBuilder() {
@@ -188,11 +198,16 @@ public boolean equals(Object obj) {
188198
}
189199

190200
/**
191-
* Creates a builder for {@code TranslateOptions} objects given an api key. For instructions on
192-
* how to get an API key see <a href="https://cloud.google.com/translate/v2/quickstart">Translate
193-
* quickstart</a>.
201+
* Returns a default {@code TranslateOptions} instance.
202+
*/
203+
public static TranslateOptions defaultInstance() {
204+
return builder().build();
205+
}
206+
207+
/**
208+
* Returns a builder for {@code TranslateOptions} objects.
194209
*/
195-
public static Builder builder(String apiKey) {
196-
return new Builder(apiKey);
210+
public static Builder builder() {
211+
return new Builder();
197212
}
198213
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.translate.testing;
18+
19+
import com.google.cloud.RetryParams;
20+
import com.google.cloud.translate.TranslateOptions;
21+
22+
/**
23+
* Utility to create a remote translate configuration for testing. Translate options can be obtained
24+
* via the {@link #options()} method. Returned options have custom
25+
* {@link TranslateOptions#retryParams()}: {@link RetryParams#retryMaxAttempts()} is {@code 10},
26+
* {@link RetryParams#retryMinAttempts()} is {@code 6}, {@link RetryParams#maxRetryDelayMillis()}
27+
* is {@code 30000}, {@link RetryParams#totalRetryPeriodMillis()} is {@code 120000} and
28+
* {@link RetryParams#initialRetryDelayMillis()} is {@code 250}.
29+
* {@link TranslateOptions#connectTimeout()} and {@link TranslateOptions#readTimeout()} are both set
30+
* to {@code 60000}.
31+
*/
32+
public class RemoteTranslateHelper {
33+
34+
private final TranslateOptions options;
35+
36+
private RemoteTranslateHelper(TranslateOptions options) {
37+
this.options = options;
38+
}
39+
40+
/**
41+
* Returns a {@link TranslateOptions} object to be used for testing.
42+
*/
43+
public TranslateOptions options() {
44+
return options;
45+
}
46+
47+
/**
48+
* Creates a {@code RemoteTranslateHelper} object for the given API key.
49+
*
50+
* @param apiKey API key used to issue requests to Google Translate.
51+
*/
52+
public static RemoteTranslateHelper create(String apiKey) {
53+
TranslateOptions translateOptions = TranslateOptions.builder()
54+
.apiKey(apiKey)
55+
.retryParams(retryParams())
56+
.connectTimeout(60000)
57+
.readTimeout(60000)
58+
.build();
59+
return new RemoteTranslateHelper(translateOptions);
60+
}
61+
62+
/**
63+
* Creates a {@code RemoteStorageHelper} object.
64+
*/
65+
public static RemoteTranslateHelper create() {
66+
TranslateOptions translateOption = TranslateOptions.builder()
67+
.retryParams(retryParams())
68+
.connectTimeout(60000)
69+
.readTimeout(60000)
70+
.build();
71+
return new RemoteTranslateHelper(translateOption);
72+
}
73+
74+
private static RetryParams retryParams() {
75+
return RetryParams.builder()
76+
.retryMaxAttempts(10)
77+
.retryMinAttempts(6)
78+
.maxRetryDelayMillis(30000)
79+
.totalRetryPeriodMillis(120000)
80+
.initialRetryDelayMillis(250)
81+
.build();
82+
}
83+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
/**
18+
* A testing helper for Google Translate.
19+
*
20+
* <p>A simple usage example:
21+
* <p>Before the test:
22+
* <pre> {@code
23+
* RemoteTranslateHelper helper = RemoteTranslateHelper.create();
24+
* Translate translate = helper.options().service();
25+
* } </pre>
26+
*
27+
* @see <a href="https://github.com/GoogleCloudPlatform/gcloud-java/blob/master/TESTING.md#testing-code-that-uses-translate">
28+
* gcloud-java tools for testing</a>
29+
*/
30+
package com.google.cloud.translate.testing;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.translate;
18+
19+
import com.google.api.services.translate.model.DetectionsResourceItems;
20+
import com.google.api.services.translate.model.TranslationsResource;
21+
import com.google.cloud.AuthCredentials;
22+
import com.google.cloud.BaseSerializationTest;
23+
import com.google.cloud.Restorable;
24+
25+
import java.io.Serializable;
26+
27+
public class SerializationTest extends BaseSerializationTest {
28+
29+
private static final String API_KEY = "apiKey";
30+
private static final String LANGUAGE = "en";
31+
private static final float CONFIDENCE = 0.42F;
32+
private static final DetectionsResourceItems DETECTION_PB =
33+
new DetectionsResourceItems().setLanguage(LANGUAGE).setConfidence(CONFIDENCE);
34+
private static final Detection DETECTION = Detection.fromPb(DETECTION_PB);
35+
private static final String TRANSLATED_TEXT = "Hello world";
36+
private static final TranslationsResource TRANSLATION_PB = new TranslationsResource()
37+
.setTranslatedText(TRANSLATED_TEXT)
38+
.setDetectedSourceLanguage(LANGUAGE);
39+
private static final Translation TRANSLATION = Translation.fromPb(TRANSLATION_PB);
40+
private static final TranslateException TRANSLATE_EXCEPTION =
41+
new TranslateException(42, "message");
42+
private static final Translate.LanguageListOption LANGUAGE_LIST_OPTION =
43+
Translate.LanguageListOption.targetLanguage(LANGUAGE);
44+
private static final Translate.TranslateOption TRANSLATE_OPTION =
45+
Translate.TranslateOption.sourceLanguage(LANGUAGE);
46+
47+
@Override
48+
protected Serializable[] serializableObjects() {
49+
TranslateOptions options = TranslateOptions.builder()
50+
.apiKey(API_KEY)
51+
.authCredentials(AuthCredentials.createForAppEngine())
52+
.build();
53+
TranslateOptions otherOptions = options.toBuilder()
54+
.authCredentials(null)
55+
.build();
56+
return new Serializable[]{DETECTION, TRANSLATION, TRANSLATE_EXCEPTION, LANGUAGE_LIST_OPTION,
57+
TRANSLATE_OPTION, options, otherOptions};
58+
}
59+
60+
@Override
61+
protected Restorable<?>[] restorableObjects() {
62+
return null;
63+
}
64+
}

gcloud-java-translate/src/test/java/com/google/cloud/translate/TranslateImplTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ public void setUp() {
105105
EasyMock.expect(rpcFactoryMock.create(EasyMock.anyObject(TranslateOptions.class)))
106106
.andReturn(translateRpcMock);
107107
EasyMock.replay(rpcFactoryMock);
108-
options = TranslateOptions.builder(API_KEY)
108+
options = TranslateOptions.builder()
109+
.apiKey(API_KEY)
109110
.serviceRpcFactory(rpcFactoryMock)
110111
.retryParams(RetryParams.noRetries())
111112
.build();

0 commit comments

Comments
 (0)