Quick Tip: Benchmark your System Using Integration Tests
Whether it's an API, database access, or in-depth calculations, you want it to be fast. Here's a quick tip to identify code that hinders performance.
While your unit tests are extremely important, there are times when you need to gauge your code as to how fast it runs and determine bottlenecks in your system.
There are utilities out there to evaluate how well your code is performing (like dotTrace Profiler from JetBrains), but you don't need to purchase anything for performance metrics.
A unit test tests the smallest component or part of an application, does not connect to any outside resource, and is strictly isolated and independent. You can run them as much as you want since no environment affects the outcome.
Integration Tests are exactly as they sound. They test a certain group of components or subsystems in an application to confirm they run as expected. Usually, it's in a development or QA environment with everything connected (Web API, Database, etc.)
I only include Integration tests in my code when I want to test certain questionable components or when I have complex logic that requires external data.
There are times when I need code to be crazy-optimized to simulate running in a production environment.
A Simple Example
Let's look at a real-world example with one of my controllers.
My HomeController unit test may look simple, but it returns a lot of data from multiple result sets in the form of the HomeViewModel.
As a sidenote, this is simply a read-only blog. When I retrieve the data, I have a repository caching the data so it doesn't have to hit the database. It returns the same set of data for every request along with a cached page response. The caching mechanism is simply not included in this integration test.
[TestMethod] [TestCategory("Integration")] public void ThenReturnTheHomeViewModel() { // Arrange var controller = new HomeController();
// Act var result = controller.Index() as ViewResult; var model = result.Model as HomeViewModel;
// Assert Assert.IsNotNull(result); Assert.AreEqual("DanylkoWeb | Mobile and Web "+ "Development using Microsoft Technologies", model.Title); }
When the Index is executed, a single database call is made and data is returned.
As we all know, we need this data (like yesterday) to show our audience we have a fast website.
Time Benchmark
One of the easiest ways to test the speed of our code is to turn our integration test into a benchmark for our controller.
We create a new integration test and add a stopwatch to compare the results.
[TestMethod] [TestCategory("Integration")] public void ThenGaugeTheResultOfTheHomeViewModel() { // Arrange var controller = new HomeController();
var sw = new Stopwatch(); sw.Start();
// Act var result = controller.Index() as ViewResult; var model = result.Model as HomeViewModel;
sw.Stop(); var duration = sw.Elapsed.Seconds;
// Assert // Make sure our call is less than 2 seconds Assert.IsTrue(duration < 2); }
Once we know how much time it takes, we can dig in further and add additional tests to other lower-level methods to optimize performance.
Conclusion
Using integration tests can not only prove your system functions as expected, but it can also create a performance tool to help you optimize systems.
Definitely a plus when running it through continuous integration.
Keep on the lookout for other ways to use unit tests and integration tests. The more tests you have for your code, the more confident you'll be releasing a solid product.
How are you detecting bottlenecks in your own code? What do you use to detect slow performing code? Post your comments below and let's discuss.