There's a famous line in software development:
“It works on my machine!”
Translation: a developer didn't bother to test the code elsewhere or forgot to simulate slow network conditions and simply assumed it would work everywhere. The functionality then breaks in the co-workers’ machines, the build system, or the customers' hands. The developer is clueless about the cause of failure. “But it works on my machine!”
As layers of complexity are added to this problem — think mobile apps and shaky Internet connections — the plot thickens. So we coined a different phrase. Something along the lines of “Test it, so you don’t regret it.” But let’s begin at the root of the problem: software.
There are only two ways for a developer to create software that works on other machines:
- Testing it under as many conditions as possible and hope for the best.
- Requiring other devices to be as close as possible to the one on which the software was developed.
The second alternative might seem strange, but it was very common in the Web’s early days when websites were optimized for Microsoft Internet Explorer 5.5 in an 800x600 screen resolution.
It Also Works on my Smartphone
When developing mobile apps, this weird phenomenon can also occur. You can just hear that little voice: “It works on my device!”
There isn't a good excuse not to test your application on as many devices as possible. Developers for iOS know they should try their apps on both low and high-end models. If it works in these, it should work in everything in the middle, right?
Android developers, on the other hand, know that there are just too many devices. This is why they test a few devices they can get their hands on and — fingers crossed — hope for the best on all the others. It usually works.
It's often not practical to acquire many phones for testing, so developers can also rely on services, such as Amazon Web Services (AWS) Device Farm or Xamarin Test Cloud. These are usually enough to test and make apps work almost everywhere.
And Then You Turn on the Internet
In the mobile world, there's another dimension to this problem: “It works on my Wi-Fi!”
Besides all the different devices developers have to consider, it is also essential to bear in mind the need to simulate slow connection conditions for apps that rely on network access.
Good developers write software with the offline first motto in mind. This means writing apps that behave well when there's no connectivity and act even better when there is. Testing for offline and online behavior is as easy as turning on or off the phone's airplane mode. But these two extremes don't cover the whole gradient required to simulate slow network conditions.
There isn't just offline or online. There's lie-fi, GPRS, 2G, EDGE, 3G, 4G, 5G, and Wi-Fi. And there's switching between all these network conditions while the app runs. Since it’s easy to test offline vs. online, applications are often designed to only function with these two states. The result? Apps that work well both offline and online (in good network conditions) but perform poorly under bad connectivity, sometimes to the point of complete unusability.
It turns out, “it works on my Wi-Fi” doesn’t mean “it works on every mobile network,” as connectivity can vary significantly. A key factor for building robust apps is to simulate poor network conditions to make testing more accessible to developers.
How to Simulate Slow Network Conditions
Some basic tools can help you simulate slow connection scenario. If you're developing a website or a hybrid app, one option is to use Chrome DevTools' network emulation.
While this is a good starting point to simulate slow network conditions, it's far from perfect. For hybrid apps, it only simulates traffic received through WebView, but not native parts. And although it worked well regarding bandwidth, it didn’t simulate latency very accurately.
Latency is critical to simulate poor network conditions as it has a massive impact on performance, drastically affecting the time it takes to establish a connection. Chrome DevTools can't test scenarios where you get other apps competing for limited bandwidth. For example, when you want to test how your app behaves when the user is uploading photos or videos through another app.
For Windows users, there's a software called Clumsy that easily adds latency and a few other things, such as drop rates. Unfortunately, it doesn't have an option to limit bandwidth easily.
On Mac OS X, you can throttle bandwidth when sharing your network. But you also don't have much control over latency.
Linux offers the most comprehensive solution to simulate slow connection settings and the one that's most difficult to learn and use. In Linux, there are configurable packet schedulers where you can set up traffic control rules. You can set up a packet queuing discipline that limits bandwidth (such as HTB) on top of another queuing discipline that introduces delays or losses (such as netem).
However, this still didn’t work for our Wi-Fi. We were looking for a solution to simulate slow network conditions that could be used on any device because we were interested in using real mobile devices in different connectivity scenarios.
Network Setup Made Easy
To simulate poor network conditions in a simple way, we went with the Linux solution, which includes traffic control. Because it’s not the most intuitive option, we wrapped it up in a rudimentary but easy-to-use UI and complemented it with a tiny yet effective bow: a Raspberry Pi device (for it to work, you need to use version 3 or later).
The Raspberry Pi makes an excellent choice because it’s cheap and comes with a built-in Wi-Fi antenna and network cable (ethernet) port. This makes it an inexpensive device that can provide a conditioned Wi-Fi network, which throttles access to the rest of the Internet.
To use this system, we connect the device which we want to test our app on to the Wi-Fi network provided by our emulator (the Raspberry Pi). We configure the emulator for the desired network conditions, and simulate slow connection conditions that affect all devices in its Wi-Fi network.
Getting a Raspberry Pi is easy. To turn it into a network emulation device, you can use the same scripts we do, which we made available on GitHub.
Having an easy way to simulate slow network conditions for their applications makes developers more likely to do it, which means addressing problems before they hit users.
We’ve used this system on a number of projects to make sure the apps would perform well. The thing with testing is that either you do it, or your users will end up doing it for you (along with the bad reviews once things fail). Remember to test it, so you don’t regret it. After all, when users complain that your app doesn’t work, you can’t just say: “Well, it works on my Wi-Fi...”