00:00:20.519
Hello, everyone! I work at Engine Yard; my name is Shai. I'm not really shy, although I always get that when I introduce myself. You can find me on Twitter at @shyar, which is my general internet handle.
00:00:33.079
I want to start off by sharing a tweet that I liked a lot. It says, 'Not having an API in 2012 is like not having a website in 1998.' I feel like we are currently in a state of the industry that's very similar. There are many marketing buzzwords like 'software as a service,' 'platform as a service,' and 'infrastructure as a service.' My roommate interacts with 'razors as a service' — all this stuff basically means having an API. Having a product that has an API is essential. Moreover, there’s a lot of discussion around taking a big monolithic application and splitting it into distributed service-oriented architecture. These various systems interact with APIs, and this stuff is incredibly important.
00:01:48.720
Today, I want to focus on how we test these APIs. Specifically, I will talk about how we test server-client APIs. I’ll discuss scenarios where we have control over both the server and the client. While there will be other scenarios you may encounter, this is what I'll concentrate on, particularly in the context of developing them together, with JSON as the HTTP endpoint.
00:02:05.119
This is my guitar, and I play music with a band on the weekends. I love playing music, which is important because it sets the context for the story of developing this API. This API will be developed for a music-labeling company. When I say 'we,' I’ll be referring to this company.
00:02:19.359
I want to introduce the characters involved in this development. We will have a server developer, a client library developer who will create a client that consumes the API, and then there’s an app developer who will consume that library to interact with the API. This app developer isn’t part of the company, but he will be using the product.
00:02:40.919
In this setup, the server will feature two endpoints: a POST and a GET HTTP endpoint. It's going to be a simple REST interface. The API will deal with songs, where you can post the words and the title of the song. This will constitute our domain model, which includes a title and the song's lyrics.
00:02:56.080
We are also going to have a GET endpoint to retrieve the lyrics for that song, provided we pass the song title. I’ll assume that the titles are unique, meaning you cannot post another song with an already existing title. The client will essentially be structured to instantiate a new client object that contains methods for posting a song and getting a song, which will interact with that REST API we’ve created. You can pass the title, get the words back — it’s pretty simple.
00:03:41.040
We want to ensure that consumer applications can easily use that library, making the testing process quick, efficient, and reliable. Just a quick question for the audience: Who here has used Fog? Great! Are you familiar with Fog's mocking interface? Not quite as many, but essentially, Fog has a really cool backend where you can use 'fog.mock', allowing you to interact with Amazon's API, and everything happens in memory quickly.
00:04:01.000
There are various other gems that function similarly. Our goal is to create this client with a mocking interface that can be easily interacted with in third-party apps while maintaining speed and reliability. Now, to reiterate our objectives, we want to create an API that musicians can use to store songs, build a client library for consumer applications, and make testing easy for these applications.
00:04:44.160
So how do we actually test these pieces? I interact with APIs daily, either writing one or coordinating with various APIs. I'm going to go through some approaches I've encountered: isolated approaches, sandbox approaches, fake servers, and mappers. These are just names I created, and I want to run through them.
00:05:38.879
The first step in developing a server and client is to test both components without early consideration for integrating paths. You might simplify testing by just testing the server's POST method without thinking about a good integration path. You could create a simple demonstration, using a POST request to take in the title and store it in a database, making sure to return a JSON response confirming the action.
00:06:13.499
Then, for validation, you would create a GET endpoint to retrieve the song by name, fetching it from the database and returning the song lyrics through a JSON response. The tests for these would also resemble how the server behaves under test conditions.
00:06:49.280
However, the client must be set up to mock the server interactions because you wouldn’t be directly talking to a live server during the tests. Tools like WebMock can be handy here. We don’t validate the backend; instead, we essentially mock it. But mocking means that if the server changes, the tests can still pass, creating a false sense of security for the client developer.
00:07:22.360
If the server API changes and the client tests pass regardless, that's problematic. An immediate response might be the musician attempting to use the client, leading to frustration if the server-side changes haven’t been reflected in the client.
00:08:11.360
To address this, instead of purely relying on mocking, we can deploy a real server somewhere designated as a sandbox environment for client tests. This allows us a full representation of operations, maintaining integrity between server and client tests by engaging in real server interactions.
00:08:49.839
While this improves test accuracy, establishing a sandbox involves setup time. Solutions like Heroku or Engine Yard allow for local server runs, but these may impede rapid feedback and continuous development workflows. There's a trade-off; sandbox tests are favorable in terms of representation, but they can significantly slow down developers due to the extra time taken.
00:09:39.840
Further, there are issues with maintaining unique titles within this sandbox, leading to validation errors impacting reproducibility in tests. The client developer may have trouble controlling the sandbox state, creating inconsistencies.
00:10:14.199
Moreover, sometimes you’ll find yourself with slower tests due to traversing network paths and parsing JSON layers, which may delay the iteration speed you want during development. In certain scenarios, if there's a unique song limit, test setups become complex.
00:10:59.300
You may need to create and manage conditions for more significant tests, stressing the limitations of API capabilities such as delete methods or interacting with third-party sandboxes.
00:11:39.799
It's essential to highlight that the directions taken within this theme of testing approaches profoundly impact development outcomes. Thus, having a validated mock representation provides considerable advantages not only within local development but also extends to third-party applications utilizing that API.
00:12:09.639
We can summarize this by acknowledging that methods which comprise maintaining one API definition have notable advantages, but it's critical to ensure code clarity and establish comprehensive test environments.
00:12:55.360
The next approach, involving creating a fake server, allows both server and client developers to share code more efficiently. By employing something like Sinatra, actively using in-memory hashes can replicate the API behavior without needing a complex backend, focusing solely on the API interactions which remain reliable across both test frameworks.
00:14:24.639
While this method facilitates efficient testing, it urges the importance of ensuring both real and fake tests remain in sync to validate outcomes consistently. When utilizing this design for CIs (Continuous Integration), developers maintain quick feedback loops while ensuring server-like testing scenarios where it counts.
00:15:13.840
The proposed methodology of toggling between real and fake server testing ensures that front-end applications retain high confidence in behavior consistency, reinforcing the value of rigorous test environments.
00:15:56.080
Again, combining silos of application logic through appropriate libraries bolsters the testing framework. This helps maintain efficient channels when interacting with diverse server configurations, creating stable and maintainable pipelines.
00:16:40.000
As we explore other approaches, it’s notable that creating a sound client representation significantly enhances the development journeys of third-party app developers, making their tasks smoother and less cumbersome.
00:17:23.000
In essence, the 'mapper' style of development allows for one coherent repository that can effectively serve the test environments for both fake and live applications. This centralizing approach fosters a seamless integration that simplifies the interaction dynamics characteristic of client development.
00:18:57.000
However, it's vital to strike a balance between maintainability and complexity within such models, as developers cross those paradigms from real to fake, thereby ensuring clear paths for others working on the same code base.
00:19:29.000
The advantages of this duality—having a central mapping between real and fake implementations—cannot go unmentioned. It signifies a robust testing strategy where real API behaviors align with expected outcomes against fake servers.
00:20:10.000
I hope the insights shared today resonate, and perhaps you'll consider varying approaches to API testing moving forward to wisely adapt to different working contexts.
00:20:59.239
Finally, I’d like to scan through some of the gems mentioned in my talk, such as RClient, Faraday, Fake Web, Real Web, and Sinatra, to foster interest in enhanced API testing frameworks.
00:21:35.079
I want to express gratitude to the audience for this chance to share insights and encourage you to explore more about the emerging concepts within API developments and testing frameworks.
00:22:22.239
Thank you for your attention, and I’m looking forward to further discussions on this stimulating topic. I'll also be sharing slides and additional resources via Twitter.