Skip to content

Commit bec9f05

Browse files
author
Robert-Jan Huijsman
authored
Make the integration test fully-automatic. (#81)
This entails two major changes: - In the Cloud Functions, keep track of which tests pass, and return 200 "PASS" when all tests pass, or 500 "FAIL - [debug-info]" when they don't. - On the client-side, trigger the HTTP function and interpret the return code as a pass or fail. Also tries to improve the readability of 'run_tests.sh' by indenting appropriately, and improve the usability by more clearly indicating whether tests have passed or failed.
1 parent b5ead22 commit bec9f05

File tree

4 files changed

+84
-34
lines changed

4 files changed

+84
-34
lines changed

integration_test/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ How to Use
66
Run the integration test as follows:
77

88
```bash
9-
firebase use $YOURPROJECTID # add your own project
9+
firebase init # Don't choose to use any features, select your project.
1010
./run_tests.sh
1111
```
1212

13-
Follow the instructions output by the script. You'll click on a number of HTTPS function links. The integration test for HTTPS is that it properly kicks off other integration tests and redirects you to the database console. From there the other integration test suites will write their results back to the database, where you can check the results.
13+
The tests run fully automatically, and will print the result on standard out. The integration test for HTTPS is that it properly kicks off other integration tests and returns a result. From there the other integration test suites will write their results back to the database, where you can check the detailed results if you'd like.

integration_test/functions/src/index.ts

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Request, Response } from 'express';
77
export * from './pubsub-tests';
88
export * from './database-tests';
99
export * from './auth-tests';
10+
const numTests = Object.keys(exports).length; // Assumption: every exported function is its own test.
1011

1112
firebase.initializeApp(_.omit(functions.config().firebase, 'credential')); // Explicitly decline admin privileges.
1213
admin.initializeApp(functions.config().firebase);
@@ -16,7 +17,7 @@ export const integrationTests: any = functions.https.onRequest((req: Request, re
1617

1718
const testId = firebase.database().ref().push().key;
1819

19-
Promise.all([
20+
return Promise.all([
2021
// A database write to trigger the Firebase Realtime Database tests.
2122
// The database write happens without admin privileges, so that the triggered function's "event.data.ref" also
2223
// doesn't have admin privileges.
@@ -33,8 +34,37 @@ export const integrationTests: any = functions.https.onRequest((req: Request, re
3334
admin.auth().deleteUser(userRecord.uid);
3435
}),
3536
]).then(() => {
36-
// On test completion, redirect the user to the Firebase RTDB dashboard, to
37-
// see the results stored there.
38-
resp.redirect(`https://${process.env.GCLOUD_PROJECT}.firebaseio.com/testRuns/${testId}`);
37+
// On test completion, check that all tests pass and reply "PASS", or provide further details.
38+
console.log('Waiting for all tests to report they pass...');
39+
let ref = admin.database().ref(`testRuns/${testId}`);
40+
return new Promise((resolve, reject) => {
41+
let testsExecuted = 0;
42+
ref.on('child_added', (snapshot) => {
43+
testsExecuted += 1;
44+
if (!snapshot.val().passed) {
45+
reject(new Error(`test ${snapshot.key} failed; see database for details.`));
46+
return;
47+
}
48+
console.log(`${snapshot.key} passed (${testsExecuted} of ${numTests})`);
49+
if (testsExecuted < numTests) {
50+
// Not all tests have completed. Wait longer.
51+
return;
52+
}
53+
// All tests have passed!
54+
resolve();
55+
});
56+
}).then(() => {
57+
ref.off(); // No more need to listen.
58+
return Promise.resolve();
59+
}).catch(err => {
60+
ref.off(); // No more need to listen.
61+
return Promise.reject(err);
62+
});
63+
}).then(() => {
64+
console.log('All tests pass!');
65+
resp.status(200).send('PASS');
66+
}).catch(err => {
67+
console.log(`Some tests failed: ${err}`);
68+
resp.status(500).send(`FAIL - details at https://${process.env.GCLOUD_PROJECT}.firebaseio.com/testRuns/${testId}`);
3969
});
4070
});

integration_test/functions/src/testing.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ export class TestSuite {
3939
let sum = 0;
4040
results.forEach((val) => sum = sum + val.passed);
4141
const summary = `passed ${sum} of ${running.length}`;
42+
const passed = sum === running.length;
4243
console.log(summary);
43-
const result = { summary, tests: results };
44+
const result = { passed, summary, tests: results };
4445
return firebase.database().ref(`testRuns/${testId}/${this.name}`).set(result);
4546
}).then(() => null);
4647
}

integration_test/run_tests.sh

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,47 @@
11
#!/bin/bash
2-
echo "#### Building SDK..." &&
3-
(cd ../ && rm firebase-functions-*.tgz && npm run build:pack &&
4-
mv firebase-functions-*.tgz integration_test/functions/firebase-functions.tgz) &&
5-
echo "#### Installing dependencies..." &&
6-
(cd functions && npm install) &&
7-
echo "##### Deploying empty index.js to project..." &&
8-
./functions/node_modules/.bin/tsc -p functions/ && # Make sure the functions/lib directory actually exists.
9-
echo "" > functions/lib/index.js &&
10-
firebase deploy --debug 2> ./deploy-debug.log &&
11-
echo &&
12-
echo "##### Project emptied. Deploying functions..." &&
13-
./functions/node_modules/.bin/tsc -p functions/ &&
14-
firebase deploy --only functions --debug 2> ./deploy-debug.log &&
15-
echo &&
16-
echo "##### Please click the 'integrationTests' link above!" &&
17-
read -n1 -r -p "##### Press [return] when you've confirmed the tests have passed." &&
18-
echo "##### Re-deploying the same functions, to make sure updates work..." &&
19-
firebase deploy --only functions --debug 2> ./deploy-debug.log &&
20-
echo &&
21-
echo "##### Please click the 'integrationTests' link above!" &&
22-
read -n1 -r -p "##### Press [return] when you've confirmed the tests have passed." &&
23-
echo "##### Removing all functions" &&
24-
echo "" > functions/lib/index.js &&
25-
firebase deploy --debug 2> ./deploy-debug.log &&
26-
rm functions/firebase-functions.tgz
27-
echo &&
28-
echo "##### Done! Please verify that your project is empty."
2+
(
3+
echo "##### Building SDK..." &&
4+
(
5+
cd ../ &&
6+
rm -f firebase-functions-*.tgz &&
7+
npm run build:pack &&
8+
mv firebase-functions-*.tgz integration_test/functions/firebase-functions.tgz
9+
) &&
10+
echo "##### Installing dependencies..." &&
11+
(
12+
cd functions &&
13+
npm install
14+
) &&
15+
echo "##### Deploying empty index.js to project..." &&
16+
./functions/node_modules/.bin/tsc -p functions/ && # Make sure the functions/lib directory actually exists.
17+
echo "" > functions/lib/index.js &&
18+
firebase deploy --only functions --debug 2> /dev/null &&
19+
echo &&
20+
echo "##### Project emptied. Deploying functions..." &&
21+
./functions/node_modules/.bin/tsc -p functions/ &&
22+
firebase deploy --only functions --debug 2> /dev/null &&
23+
echo &&
24+
echo "##### Running the integration tests..." &&
25+
funcURL=$(tail -n 1 firebase-debug.log | awk '{ print $5 }') && # URL is printed on last line of log.
26+
wget --content-on-error -qO- $funcURL &&
27+
echo &&
28+
echo "##### Integration test run passed!" &&
29+
echo "##### Re-deploying the same functions, to make sure updates work..." &&
30+
firebase deploy --only functions --debug 2> /dev/null &&
31+
echo &&
32+
echo "##### Running the integration tests..." &&
33+
wget --content-on-error -qO- $funcURL &&
34+
echo &&
35+
echo "##### Integration test run passed!" &&
36+
echo "##### Removing all functions" &&
37+
echo "" > functions/lib/index.js &&
38+
firebase deploy --only functions --debug 2> /dev/null &&
39+
rm functions/firebase-functions.tgz &&
40+
rm functions/firebase-debug.log &&
41+
echo &&
42+
echo "##### All tests pass!"
43+
) || (
44+
echo &&
45+
echo "XXXXX Something failed XXXXX" &&
46+
false # Finish with an error code.
47+
)

0 commit comments

Comments
 (0)