Skip to main content

More iOS Testing

Coming back to my project with a failing test worked great. I was able to immediately run my tests, see which one was failing and then figure out where to go from there. So I figured out my date issues and now have that logic working as I want. Next up is to test out the functionality in the app.

Running through the app I found some more issues here and there. Another good reminder that while Unit Tests will help prevent bugs and regressions, there is still a need for manual testing as well. If it makes sense to add more Unit Tests as you find issues from your manual tests, then add those in as well.

I was able to fix up the issues I found from manual testing and moved on to getting the app on my actual phone. This ended up being pretty easy and straight forward. I needed to get a certificate from Apple to sign my app, but Xcode took care of most of that and I was able to publish the app to my phone pretty easy.

I have my own little ToDo list that I have been working through and adding to as I come up with new features that I want in the app or find issues that are broken. One of the main benefits to TDD is that you should be able to create a test for the smallest step that will move you forward towards the end goal. Practicing TDD for a while now has really helped me see how useful breaking up tasks into small chunks can be. and having a super simple ToDo list has allowed me to break up tasks I want to do outside of code, or at least outside of tests, into small easy to complete pieces. With this little tasks in front of me, it is not very scary to move forward, or start back up after a break, because I can just pick the first thing in the list and get to work. Because that first item is likely to be small and easy I don't have to think too hard at how to approach the problem, I can jump right in and start completing the task.

I now have a fully working app. One of the big pieces of TDD, the one that seems hardest for me, is to refactor after you have your tests working.  Given that my app is pretty simple and small, now would be a good time to go over the existing logic and see if there aren't areas that could be refactored. As an indication to the user for how they are doing in relation to their goal, I had added some logic to change the color of today's total so that as they got closer to their goal they would easily see how they were doing. As it turns out, I had not put any tests around this logic, and this logic was duplicated in a couple places.

Since the main purpose of refactoring is to remove duplication, and I have a very obvious example of duplication in front of me, it is time to refactor this code. Given that I don't have any tests in place for this logic, I will need to build tests around this logic as part of my larger refactoring. I see this as doing a little TDD cycle inside of my refactor cycle. I start by creating the class I want to hold my tests, and write my first test, by calling a class that doesn't exist, this class will be where I want my logic to end up. Then I move through the mantra: Red, Green, Refactor, until I have the new class and its logic working as desired. Then I replace the places where the original code was with my new code. I have greater confidence now in the logic behind these tests, I have reduced the complexity of my app by consolidating duplicate code, and I have set myself up for easier modification in the future.

So I have gone through my little app and refactored a bit, added some tests, and have some insights into plugin/addons/enhancements to Xcode that would be nice for testing purposes. First and most obviously is that I have been running Xcode in full screen mode. Its great for focusing on the code and what is in front of me. However, when I run my tests, it launches the simulator and with launching the simulator it takes me to another window that is not Xcode, I see the simulator boot up and then I get a notification of wether or not my tests were successful. This is definitely not the ideal way this should be handled. Unless you are running UI tests, which Xcode ought to be smart enough to know, I don't think you would ever want to launch the simulator. At the very least it could launch the simulator behind the scenes and keep Xcode in the forefront, perhaps this isn't a problem if you aren't doing Full-Screen.

Another tool I miss very much is NCrunch. NCrunch is great for so many reasons. My personal favorites, and the ones I most wish were available for iOS development:

  • Continuous Tests - having this functionality would alleviate my issue with the simulator because I wouldn't need to launch anything as the building and testing would always be happening behind the scenes.
  • Real-Time Code Coverage - showing on the side of your editor which lines of code have tests covering them and which ones are failing and which ones aren't being tested at all is fantastic. Xcode does not have an easy way to see your Code Coverage, so having something that could do this would be wonderful.
  • Inline Debugging - You can also launch your tests from the Code Coverage side-bar. I can see from the red X which line of the code is causing my test to fail and I can tell NCrunch to debug all the tests that cover that line, from the Code file not the Test file. I can set a breakpoint and immediately begin figuring out what is going wrong.

For the most part, my experience with Xcode and iOS development have been exciting and positive. I have learned a bunch and have seen how the things I know from .NET can be applied to Objective-C. I still have lots of features I would like to add to my app and I expect I will continue to learn as I implement them.


Popular posts from this blog

Converting a Large AngularJS Application to TypeScript Part 1

I work on a project that uses AngularJS heavily. Recently we wondered if using a preprocesser like CoffeeScript or TypeScript for our JavaScript would be beneficial. If our team is going to switch languages, we would need to be able to convert existing code over without much pain and we would have to find enough value in switching that it would be worth the conversion. I had read an article that stated that because TypeScript is a SuperSet of JavaScript, you could convert a plain JavaScript file to TypeScript by changing the extension to .ts and not much else would need to change. I wanted to test out this claim, so I took a file that I was familiar with, an Angular Controller, and tried to convert it to TypeScript to see how much effort it would take and then try to figure out where we would benefit from using TypeScript. This is what the controller JavaScript file looked like to start out with: ( function () { 'use strict' ; angular .module( 'app'

Gamify TDD

I like it when things that would not normally be associated with games add concepts from games as a way to incentives you to accomplish things. Why simply go for a run if you can have an app that will track you and give you a gold star if you do better than you did the last time? Why go to the coffee shop that only gives you coffee if the other one will give you points that you can redeem for free drinks eventually? I was recently introduced to C odeSchool , an online training system similar to PluralSight, it has video courses and challenges you can take to prove that you retained what the video taught. CodeSchool also adds badges and tracks to your learning, so as you complete a video and its challenges you get a badge. Complete a collection of courses within a specific discipline and you become a master of that discipline. Some of these incentives are not tangible and really don't mean much in the real world, but they tend to work for me. If I start working towards a large g

Converting a Large AngularJS Application to TypeScript Part 2

In part 1 I was able to take an Angular controller written in JavaScript and convert it to a TypeScript file while doing very little to change the code. In this post I am going to explore transitioning that same controller to actually use the features provided in TypeScript. This is how I left off my controller: declare var angular: any; (function () { 'use strict'; var controller: any = function($scope){ ... } angular .module('app') .controller('controller', controller); controller.$inject = ["$scope"]; })(); While performing the translation from JavaScript to TypeScript, I would make sure at every step that the functionality I expected still worked, so if anything I did broke the system I would change it back and try again with another approach. Also if something seemed like it worked too easily, I would break it on purpose to make sure I wasn't getting a false result through browser caching a previously working