Skip to content

Commit c4a99c6

Browse files
committed
Add TestId for reduced flakiness.
1 parent 6b134b2 commit c4a99c6

File tree

5 files changed

+86
-16
lines changed

5 files changed

+86
-16
lines changed

smoke-tests/src/database/java/com/google/firebase/testing/database/DatabaseTest.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import com.google.firebase.database.FirebaseDatabase;
2929
import com.google.firebase.database.ValueEventListener;
3030
import com.google.firebase.testing.common.Tasks2;
31+
import com.google.firebase.testing.common.TestId;
3132
import java.util.HashMap;
3233
import org.junit.Rule;
3334
import org.junit.Test;
@@ -48,20 +49,24 @@ public void setValueShouldTriggerListenerWithNewlySetData() throws Exception {
4849
Task<?> signInTask = auth.signInWithEmailAndPassword("[email protected]", "password");
4950
Tasks2.waitForSuccess(signInTask);
5051

51-
DatabaseReference doc = database.getReference("restaurants").child("Baadal");
52+
DatabaseReference doc = database.getReference("restaurants").child(TestId.create());
5253
SnapshotListener listener = new SnapshotListener();
5354
doc.addListenerForSingleValueEvent(listener);
5455

5556
HashMap<String, Object> data = new HashMap<>();
5657
data.put("location", "Google NYC");
5758

58-
Task<?> setTask = doc.setValue(new HashMap<>(data));
59-
Task<DataSnapshot> snapshotTask = listener.toTask();
60-
Tasks2.waitForSuccess(setTask);
61-
Tasks2.waitForSuccess(snapshotTask);
59+
try {
60+
Task<?> setTask = doc.setValue(new HashMap<>(data));
61+
Task<DataSnapshot> snapshotTask = listener.toTask();
62+
Tasks2.waitForSuccess(setTask);
63+
Tasks2.waitForSuccess(snapshotTask);
6264

63-
DataSnapshot result = snapshotTask.getResult();
64-
assertThat(result.getValue()).isEqualTo(data);
65+
DataSnapshot result = snapshotTask.getResult();
66+
assertThat(result.getValue()).isEqualTo(data);
67+
} finally {
68+
Tasks2.waitBestEffort(doc.removeValue());
69+
}
6570
}
6671

6772
private static class SnapshotListener implements ValueEventListener {

smoke-tests/src/firestore/java/com/google/firebase/testing/firestore/FirestoreTest.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.firebase.firestore.FirebaseFirestoreException;
3030
import com.google.firebase.firestore.ListenerRegistration;
3131
import com.google.firebase.testing.common.Tasks2;
32+
import com.google.firebase.testing.common.TestId;
3233
import java.util.HashMap;
3334
import org.junit.Rule;
3435
import org.junit.Test;
@@ -41,15 +42,15 @@ public final class FirestoreTest {
4142
@Rule public final ActivityTestRule<Activity> activity = new ActivityTestRule<>(Activity.class);
4243

4344
@Test
44-
public void listenForUpdate() throws Exception {
45+
public void setShouldTriggerListenerWithNewlySetData() throws Exception {
4546
FirebaseAuth auth = FirebaseAuth.getInstance();
4647
FirebaseFirestore firestore = FirebaseFirestore.getInstance();
4748

4849
auth.signOut();
4950
Task<?> signInTask = auth.signInWithEmailAndPassword("[email protected]", "password");
5051
Tasks2.waitForSuccess(signInTask);
5152

52-
DocumentReference doc = firestore.collection("restaurants").document("Baadal");
53+
DocumentReference doc = firestore.collection("restaurants").document(TestId.create());
5354
SnapshotListener listener = new SnapshotListener();
5455
ListenerRegistration registration = doc.addSnapshotListener(listener);
5556

@@ -66,6 +67,7 @@ public void listenForUpdate() throws Exception {
6667
assertThat(result.getData()).isEqualTo(data);
6768
} finally {
6869
registration.remove();
70+
Tasks2.waitBestEffort(doc.delete());
6971
}
7072
}
7173

smoke-tests/src/main/java/com/google/firebase/testing/common/Tasks2.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,39 @@
1717
import com.google.android.gms.tasks.Task;
1818
import com.google.android.gms.tasks.Tasks;
1919
import java.util.concurrent.ExecutionException;
20+
import java.util.concurrent.TimeoutException;
2021
import java.util.concurrent.TimeUnit;
2122

2223
/** Test utilities for asynchronous tasks. */
2324
public final class Tasks2 {
2425

26+
private static final long BEST_EFFORT_DURATION = 10;
2527
private static final long WAIT_DURATION = 30;
2628
private static final TimeUnit WAIT_UNIT = TimeUnit.SECONDS;
2729

2830
private Tasks2() {}
2931

32+
/**
33+
* Waits for the task to complete.
34+
*
35+
* <p>The primary use case for this method is to perform test clean-up in a {@code finally} block.
36+
* Clean-up is inherently a best-effort task, because it might not succeed when the test is
37+
* broken.
38+
*
39+
* <p>This method will block the current thread for a short period of time. Unlike the other
40+
* methods in this class, this method is not biased towards success or failure. This method does
41+
* not throw any exceptions.
42+
*/
43+
public static void waitBestEffort(Task<?> task) {
44+
try {
45+
Tasks.await(task, BEST_EFFORT_DURATION, WAIT_UNIT);
46+
} catch (InterruptedException ex) {
47+
Thread.currentThread().interrupt();
48+
} catch (ExecutionException | TimeoutException ex) {
49+
// Ignore.
50+
}
51+
}
52+
3053
/**
3154
* Waits for the task to complete successfully.
3255
*
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2018 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.testing.common;
16+
17+
import java.util.UUID;
18+
19+
/**
20+
* A utility for generating ids for some sort of entity for testing.
21+
*
22+
* <p>Examples of test ids include paths to database documents and storage files. This class
23+
* randomly generates ids so that concurrent test runs do not share state. Ids generated by this
24+
* class are guaranteed to begin with a letter, not use special characters, and have no slashes.
25+
*
26+
* <p>This implementation returns strings 21 characters long. All ids begin with the letter {@code
27+
* t} to ensure the first character is a letter. The remaining characters are lower-case hexadecimal
28+
* characters.
29+
*/
30+
public final class TestId {
31+
32+
public static String create() {
33+
return "t" + UUID.randomUUID().toString().replace("-", "").substring(0, 20).toLowerCase();
34+
}
35+
}

smoke-tests/src/storage/java/com/google/firebase/testing/storage/StorageTest.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.firebase.storage.FirebaseStorage;
2525
import com.google.firebase.storage.StorageReference;
2626
import com.google.firebase.testing.common.Tasks2;
27+
import com.google.firebase.testing.common.TestId;
2728
import java.nio.charset.StandardCharsets;
2829
import java.util.Arrays;
2930
import org.junit.Rule;
@@ -45,17 +46,21 @@ public void getShouldReturnNewlyPutData() throws Exception {
4546
Task<?> signInTask = auth.signInWithEmailAndPassword("[email protected]", "password");
4647
Tasks2.waitForSuccess(signInTask);
4748

48-
StorageReference blob = storage.getReference("restaurants/Baadal");
49+
StorageReference blob = storage.getReference("restaurants").child(TestId.create());
4950

5051
byte[] data = "Google NYC".getBytes(StandardCharsets.UTF_8);
5152

52-
Task<?> putTask = blob.putBytes(Arrays.copyOf(data, data.length));
53-
Tasks2.waitForSuccess(putTask);
53+
try {
54+
Task<?> putTask = blob.putBytes(Arrays.copyOf(data, data.length));
55+
Tasks2.waitForSuccess(putTask);
5456

55-
Task<byte[]> getTask = blob.getBytes(128);
56-
Tasks2.waitForSuccess(getTask);
57+
Task<byte[]> getTask = blob.getBytes(128);
58+
Tasks2.waitForSuccess(getTask);
5759

58-
byte[] result = getTask.getResult();
59-
assertThat(result).isEqualTo(data);
60+
byte[] result = getTask.getResult();
61+
assertThat(result).isEqualTo(data);
62+
} finally {
63+
Tasks2.waitBestEffort(blob.delete());
64+
}
6065
}
6166
}

0 commit comments

Comments
 (0)