Writing model tests for Neo4j

neo4j-logo-2015

So over the last few weeks, I’ve been playing around with the idea of moving My.Stocked.Kitchen’s recipe and ingredient database over to a Neo4j graph database from the original MySQL relational database. My belief is that a graph DB better suits the relationship structure of recipes and ingredients (and their similar ingredients) than a traditional relational DB.

I’ve been playing around with using ActiveNode (neo4jrb/neo4j) instead of ActiveRecord, but the problem was that my models are dependent on some gems for extra capabilities such as Friendly_id and Sunspot.

Since I wasn’t able to find a sunspot_neo4j-like gem, I began working on my own. I modeled it after the original sunspot_mongoid implementation and I was very impressed with how easy and straight-forward it seemed. You can see below the code that was required to get it working:

You can find the whole source here: sunspot_neo4j

But an interesting thing happened when I finished the original implementation of sunspot_neo4j. I wanted to ensure I had some specs written that verified everything was working (supposedly that makes you a “good” developer), but wasn’t able to find a good library to use that would start up a local Neo4j instance just for the lifetime of tests. Looked like it was time to start writing a second gem designed specifically for creating specs that have a real dependency on an existing Neo4j server.

The end result ended up being me writing the neo4j_test_server gem.

For sunspot_neo4j, I had a few testing requirements that I needed this gem to provide:

  • Manage a locally running Neo4j instance (including download/startup/shutdown)
  • Hooks into Rspec for stopping, cleaning, and starting the instance during test execution
  • Support tests that require different versions of Neo4j
  • Needed to be scoped to only particular tests. I didn’t want ALL of the specs to manage a running Neo4j instance. Just the ones where I couldn’t use mocks.

And so that’s just what neo4j_test_server provides. If you follow the README on the project’s site, you’ll see exactly how to get started.

For sunspot_neo4j, I ended up with something like the following:

I required all of the necessary files within my spec_helper.rb, but you’ll notice that I add the neo4j: true tag to the tests that require a running local Neo4j instance.

When run, the neo4j_test_server gem will download, configure, and startup a Neo4j instance that your tests can connect to. I have an example/dummy Rails app setup in the spec folder that is initialized during test startup so that I can properly test the actual models a user of the gem would have in their Rails application. To me, this keeps the specs pretty clean since I don’t have to include any test models directly in the specs themselves.

I have also added some logic to the gem using Ruby’s “at_exit” method so that when the specs finish, any running Neo4j servers will automatically be shutdown. The idea was to put the system back into state it was in prior to launching the tests.

The cool thing I’m able to do with this gem is configure tests to automatically run against different versions of Neo4j without the tests having to deal too much with cleaning up after themselves. The gem takes care of all of that. If you look at the test block at line 25 above, you can see that I can simply list the versions of Neo4j that sunspot_neo4j supports and run all of my tests. Easy-peasy.

In the end, I was pretty happy with how both neo4j_test_server and sunsport_neo4j turned out. Both work for the use cases I wanted them to cover and each has rspec tests that help me verify the “correctness” of the gems as work continues on both.

Try them out for yourselves and let me know what you think.

UI Automation Basics

Is the scope of your application expanding? Is your team trying to be agile but spending too much time regression testing your app? Would you like to know the quality of your app as you’re building it? If you’ve answered yes to any of these questions, your team (and specifically your QA staff) is especially in need of TESTING AUTOMATION. Who wants to spend their time regressing a product each release when they could be spending more time with the customer or helping to design features. I certainly don’t.

I currently work on a product that’s about 10 years old. Over those ten years, it has grown, shrunk, and grown again to the point that it was becoming hard to ensure a high level of quality from release to release. In order to assist the team in the lengthly process of testing the app across areas, browsers and configurations, I began to build a UI testing framework. A unit testing framework had already been developed by the team, but we needed a way to ensure the integrity of the app across browsers as new features were being added. Here were a couple of requirements that we had in place:

  • With an expanding team, the UI was constantly changing. The UI automation framework must be maintainable to prevent constant refresh of tests due to a changing UI.
  • Tests must be written once and have the ability to be executed across environments and browsers seamlessly.
  • Triage must be quick and painless.
  • Tests should be easy to read/write by QA engineers and product developers alike.
  • Tests should be decoupled from the underlying automation tool to allow for swapping out of the framework. We weren’t entirely certain which tool we wanted to use (Selenium, Silk4J, WebDriver, etc) and didn’t want to have to start from scratch months down the line.

Over the next few posts, I’ll be detailing how we accomplished all of the goals listed above and how you too can help your team become more agile by testing faster and more effectively.