I’m a huge proponent of ‘Active Learning’ – whereby you take steps to test your understanding of information rather than just passively read documentation. By using learning tests with AWS, you’ll be able to build on concepts that are too detailed to simply enumerate on the back of a flashcard.
Don’t get me wrong, for high level concepts the humble flashcard is a great tool for the job. But there’s only so much detail you can go into with those. Since our jobs involve coding and scripting, I’d like to illustrate a different way, the “Learning Test”. It’s a technique that can be used for when you study, and it dovetails nicely with flashcards as well as working standalone.
For this article I’ll be using learning tests with AWS (specifically DynamoDB) so we target our efforts and have reference materials for our day job – so great bang for buck.
So what is a “Learning Test”?
I first stumbled across the concept of the ‘learning test’ — from the book Clean Code 4. For those unfamiliar with this term, it’s an excellent approach for developers to drill down into detail, made even easier as we’re in an age of ‘configuration as code’.
Simply put, rather than reading the documentation for software, use an available testing framework to **prove** what the documentation says. In this instance we’ll take a look at DynamoDB.
So when would we use it?
Let’s take the example of DynamoDB. You’ve come onto a new project and you’re told “we use DynamoDB as storage cos.. blah” but you don’t really know much about DynamoDB. Or you’re doing the AWS certification and you’ve heard that DynamoDB plays a big part.
How do we go about getting up to speed?
Now I know that in the case of DynamoDB there are tutorials from the AWS site but we’re going to use Learning Tests for 3 reasons.
- We might want to go in a different direction to the tutorials. Maybe I am stuck on understanding the different kind of indexes, but the starter tutorial only cover that in passing
- At work, we’re rarely dealing with just the AWS components in isolation. The simple world tutorials are a good building block, but we usually have our own domain logic that we have to learn on the job too. Since you’re in control of the tests, you get to build lessons on that too – it’s down to you what you decide to code.
- Once you have these tests checked into version control, you have an instant refresher of work you do infrequently. Just as unit tests provide a ‘common understanding’ of the system, your learning tests provide you with a reminder of your own expectations at some point in time.
This will all make more sense with a worked article. Let’s move onto an example, using DynamoDB.
Using learning tests with AWS (DynamoDB SDK Example)
I’m going to assume that you’re generally familiar with how to set up your AWS SDK from your day job. If not, you can see a Java example here.
We’ll use DynamoDB Local in this tutorial so that we don’t incur any AWS fees when doing this development. However we need to be aware that are some differences between running this and the web version. We’ll update our tests later to do both.
During this tutorial, Java is my weapon of choice, given that is my development background, so you’ll see Java and TestNG used to drive out our learning.
I’ll go ahead and setup DynamoDB Local, as per the instructions – as a first cut we can see interact with the CLI but we have no tables yet.
Mac users, you may also get a problem with security, when running this local instance, you can go ahead and allow just this program.
Next we need to set up the maven repo as per these instructions.
I now have my own maven repo ready to explore with.
Run the code samples
We’ll start by using the samples verbatim from AWS. If we follow the steps from 1 -5, we’ll have a set of java files like this.
As I create launch configs in IntelliJ for each of the examples, I run them and optionally verify using the CLI. In this instance I’m running the MoviesCreateTable.java through IntelliJ.
And then by using the CLI we can see that the operation worked as expected.
All this is well and good for manual interpretation, but we can go one better. With a bit of judicious refactoring, we can do learn what we need entirely from the SDK. If something goes wrong, we still have the CLI and the AWS documentation to guide us.
Refactor samples into tests
So let’s start with step 1 – the main method. I’ll leave the AWS samples untouched in their original package and create my own package that is more “learning centric”. That way you can compare the results and see how the transformation was made.
I’ve taken the code that sets up a DynamoDB client and a DynamoDB table and split them into components. By utilising a builder pattern, I can specify my test fixtures in a way that expresses which parts of the DynamoAPI I am testing. For example, if I only care about provisioned throughput, I can just set some defaults in the builder and leave the test uncluttered .
Another thing to note is how I have progressively built on these tests, in the first case I’m expecting a no table name error, so I use TestNG and its regex matching. Then I add the table name in but don’t have a key schema. Then I have a table name and key schema but no attribute schema. Each test has a specific criteria and they are fast to run.
NB AWS already uses the builder pattern for requests against the various APIs, for example CreateTableRequest. However I’ve used my own components to also allow for specifying the region I want, for overriding credentials and so on. You can probably just use the API directly if you like.
With the builder pattern in place, I have been able to:
- Expressed the permutation of conditions I wish to test
- Set my expectation of what will happen
- Assert the result of what will happen.
A worked example
That learning test is checking that I can’t leave the table name out. See how I use a regex to extract just the meaning from the message. But we’ll probably want to go a bit deeper than just simple validation of parameters. The full set of resources is in my bitbucket repo since there’s too much to cover in one article.
For example, I wanted to see what will happen with a provisioned throughput of 10 when I slam DynamoDB with more data than the capacity we allocated (and therefore paid for). I’m expecting it to get throttled.. but it doesn’t.
So what did happen? It turns out I need to read the docs a bit more carefully in terms of read and write capacity units. I can see the error now that I’ve checked more carefully, there is no limit..
I corrected the test, and I might even want to consider adding my misunderstanding into a flashcard if I think the overall concept might be hard for ‘future me’ to remember.
I can keep going through this for each of the steps in the tutorial, and soon I have built a suite of tests that report on the DynamoDB API.
Finally working with the real DynamoDB service
If we look at the notes here, there are warnings that the behaviour of the local setup is different from the web one. Let’s create some tests that run against the real one too, but only after we’ve got to grips with how to write a learning test for AWS.
I hope you can see how learning tests turn passive documentation reading into something a bit more fun, Not only that, docs can get out of date, not so the code! The best part of all though is that you can save all of this off into a repo as I have done, and you’ve got a permanent set of reminders, as how to how the API works. A little toolbox if you will. Also, I should mention there are some DynamoDB code samples here if you wanted a shortcut to creating your test suite.
As ever, if there is any feedback, please feel free to get in touch – all constructive feedback is welcome.