Solving a Stuck Automated UI Test on iOS

We've been using Xamarin's UITest framework quite a bit, both for standard test automation as well as some other tasks (more on that to come). Things had been working great, but after some recent upgrades to the latest versions of Xcode and the iOS tools, we were seeing our automated tests get stuck in one specific spot in the app's flow. Nothing particularly interesting was happening in this spot: it was making a network call out to our API, which was working, but the app would never actually proceed with the response it got. This only happened during test runs, so it was a scenario only triggered by the app being started by UIAutomation.

Thanks to the help of Rasmus Kromann-Larsen and Karl Krukow, I was able to get to the bottom of what was going on. As it turns out, there seems to be a bug in UIAutomation itself related to large amounts of text being output to the console. For debug builds of our app we're outputting quite a bit of diagnostic info at times that's very useful during development but never ships in production builds, and that was making UIAutomation quite unhappy. Of all the things I'd considered as possible suspects when trying to troubleshoot this issue, the console output was nowhere near the top of my list.

This output isn't really important during test runs, so we decided to just suppress all console output for them. We already had some bootstrapping code to clear out data in the app to make sure all tests start from a clean slate, so we just needed to add a couple steps to that. First, we created a TextWriter implementation that just ignores everything sent to it:

class SuppressingWriter : TextWriter  
{
    public override Encoding Encoding { get { return Encoding.Unicode; } }
    public override void Write(string value) { }
    public override void Write(bool value) { }
    public override void WriteLine() { }
    public override void Write(int value) { }
    public override void Write(char value) { }
    public override void Write(char[] buffer) { }
    public override void Write(char[] buffer, int index, int count) { }
    public override void Write(decimal value) { }
    public override void Write(double value) { }
    public override void Write(float value) { }
    public override void Write(long value) { }
    public override void Write(object value) { }
    public override void Write(string format, object arg0) { }
    public override void Write(string format, object arg0, object arg1) { }
    public override void Write(string format, object arg0, object arg1, object arg2) { }
    public override void Write(string format, params object[] arg) { }
    public override void Write(uint value) { }
    public override void Write(ulong value) { }
}

Then we just needed to redirect console output to that writer, and remove all debug output listeners:

System.Diagnostics.Debug.Listeners.Clear();  
Console.SetOut(new SuppressingWriter());  

Problem solved! This is certainly a bigger hammer than necessary to solve the immediate problem in our apps, but it did the trick and our tests are green again.

comments powered by Disqus
Navigation