Skip to content

Porting the legacy integration test suite #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
Apr 14, 2017

Conversation

hiranya911
Copy link
Contributor

This PR ports the legacy integration test suite (most of it) to run against Firebase production. This requires a Firebase project. Create a project in Firebase console, and download the service account key file. Then run the test suite as:

mvn verify -Dfirebase.it.certificate=[path/to/serviceAccountKey.json] -Dfirebase.it.url=[DB URL]

The IntegrationTestUtils class handles reading the service account key, and making it available to all integration tests.

This PR also cleans up the test sources. In particular:

  • A dependency on jackson-asl has been removed.
  • A dependency on the legacy Firebase token generator has been removed.
  • TestConstants class removed.
  • Most of the methods in TestUtils, which were used by the old test suite has been modified, and moved to IntegrationTestUtils.
  • Removed the ListBuilder class.
  • The DeepEquals class has been removed and replaced with the DeepEquals class from cedarsoftware-utils library.
  • Removed the PerformanceBenchmarks and SynchronousConnection classes. We can fix and add them later if necessary.

There's a lot more that can be done to fix and improve the integration test suite, but I feel this is a great starting point since we didn't have a working test suite for a while (and definitely not one that runs against Firebase prod). I will send in more improvements in future PRs.

Hiranya Jayathilaka and others added 30 commits April 5, 2017 19:12
* Reformatted all source files
* Separated unit and integration tests
* Added maven checkstyle plugin
* Got the basic build and unit tests working
* Scrubbed the codebase for private keys, certificates etc.
Copy link

@mikelehen mikelehen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is too big to actually review in detail, but I tried to spot-check it (especially the utils and stuff) and overall it looks good and clearly gets us into a much better state. Thanks for tackling! I left a few questions / comments.

fail("Found error on run loop");
}
}
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why this code is going away? Have you verified that an exception on the test event target still causes tests to fail and the error to be reported nicely?

I honestly don't remember the full context, but I assume if you e.g. added a snapshot listener and the listener implementation threw an exception (e.g. because a test assertion failed), it wasn't being reliably reported in a friendly way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method works with a set of made up contexts and a TestEventTarget. The new integration tests uses the actual database context and the actual ThreadPoolEventTarget, and therefore this method will not work for us anymore. Also we were calling this method from tearDown events, which is kind of broken.

However, I do understand the point you're making about assertions checked in async event handlers. I've fixed a bunch of them so that the assertions are checked outside the event handlers in a blocking manner. However, I'm pretty sure there are plenty left to fix, which I will get around to eventually. The good news is however, whenever an async event handler encounters a failed assertion it throws an exception, which Maven logs to the console. I don't see any of those in the test output.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hrm... Are you saying that right now, asynchronous test failures log an exception instead of fail the test? And the plan going forward is to rewrite them to not do asynchronous assertions? I'm not sure I'm a fan of that... It seems like a lot of work and easy to forget / miss cases. What was the motivation for undoing the existing approach?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't be running assertions in tearDown methods. This can lead to test environment not getting cleaned up properly. Also this requires using a non-default RunLoop implementation that keeps track of errors. I'm not sure if that's a good idea, since we will not be testing the actual run loop that a typical users get.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me also try to figure out how often we do async assertions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, we do this kind of thing often enough, so we should implement some way to check for async errors. But this requires messing with both RunLoop and EventTarget. Specifically we need to modify them during tests to catch errors. This is going to require some work, and so I'd rather do them later.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. Just keep in mind that means many test failures may not fail travis / whatever we're using for CI and thus may not be caught until later (if/when somebody happens to notice the log messages I guess). Given we're not making a lot of changes, this is probably okay. But if we start doing nontrivial development or start receiving pull requests from the community, this debt could easily bite us.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted. I've been experimenting with some changes, and I think I have a way to fix this properly. I will send a PR with the fix soon, once the open sourcing stuff is sufficiently under control. Thanks Michael for pointing this problem out.

FirebaseApp.initializeApp(
new FirebaseOptions.Builder()
.setCredential(FirebaseCredentials.fromCertificate(ServiceAccount.EDITOR.asStream()))
.setDatabaseUrl("http://tests.fblocal.com:9000")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to point this elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now only used in unit tests (DataSnapshotTest, DefaultPersistenceManagetTest etc.). So it doesn't matter where it points to.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be consistent, I've changed this to admin-java-sdk.firebaseio.com

TestRunLoop runLoop = new TestRunLoop();
DatabaseConfig config = new DatabaseConfig();
config.setLogLevel(Logger.Level.DEBUG);
config.setLogLevel(Logger.Level.WARN);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why you're changing this. It's probably fine, but the logs are often useful for debugging test failures.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The debug logs clutter up the test output. Ideally we should use a proper logging framework like JUL or SLF4J, so that the user/developer can control the log level (for both released code, and tests) externally. I'm planning to do this in the future. But for now I'd prefer to have a simple and less verbose test output as the default.

import java.net.URI;
import org.junit.Test;

public class RepoInfoTest {

@Test
public void getConnectionURLTestOverloadWorks() {
final String repo = "tests";
final String server = "fblocal.com:9000";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess maybe this is okay because we're not actually starting a connection, but I think we should remove as many references to fblocal.com as possible. This is a legacy hack we used for testing against a local Firebase instance, and more problematically, fblocal.com is a real domain name and we do not own it. :-/

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably switch to fb.local or something instead if we have references we want to keep.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to admin-java-sdk.firebaseio.com

info.internalHost = info.host;
info.secure = false;
info.namespace = TestConstants.TEST_REPO;
info.namespace = repo;
URI url = info.getConnectionURL(null);
assertEquals("ws://tests.fblocal.com:9000/.ws?ns=tests&v=5", url.toString());

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to firebaseio.com URL

@@ -47,15 +46,13 @@ public void startListening(
ListenHashProvider hash,
SyncTree.CompletionListener onListenComplete) {
Path path = query.getPath();
logger.debug("Listening at " + path + " for Tag " + tag + ")");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why remove all this logging?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was also to prevent the default test output from getting cluttered up. But I've added it back with log level set to WARN, so it won't be as verbose. We can fix it better once the logging stuff is implemented properly.

import org.junit.BeforeClass;
import org.junit.Test;

public class KeepSyncedTestIT {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is IT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stands for Integration Test. Maven surefire and failsafe plugins use this naming convention to differentiate between unit tests and integration tests. I will document this in my next pull request.

@hiranya911
Copy link
Contributor Author

I've added some of the logging code back, and dropped all references to fblocal domain.

import java.net.URI;
import org.junit.Test;

public class RepoInfoTest {

@Test
public void getConnectionURLTestOverloadWorks() {
final String repo = "tests";
final String server = "admin-java-sdk.firebaseio.com:9000";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of the port in all three places in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@mikelehen
Copy link

Thanks for the changes. LGTM.

Copy link

@jwngr jwngr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks Hiranya!

@hiranya911 hiranya911 merged commit 76dd3d2 into master Apr 14, 2017
@hiranya911 hiranya911 deleted the hkj-db-integration-tests branch April 14, 2017 16:52
@jwngr jwngr removed their assignment Apr 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants