Skip to main content

First Tests for iOS and Objective-C

Now that I have some basic UI elements working and some Data Objects defined and those Data Objects are persisted to a Database. Its time to start working on some logic, and before we do any logic, we want to have Tests in place. Red of the Red, Green, Refactor mantra. I want to keep track of every entry made throughout a day, and then when the day changes over, consolidate all of the previous day's records into 1 history record so that the user will be able to see how they have progressed over time. Date logic is always fun, so I am really glad to be starting out with a Test rather than assuming that my date comparisons will work as I expect them.

In .NET you denote a Test Method by giving it an Attribute, and then treating it like any other method. Here in Xcode, you denote a Test Method, but having the method's name start with lowercase test, and then you add the test name after it. I've grown accustomed to naming my Test Methods very verbosely and descriptively to make sure that their intent is clear. needing to start the name with test probably won't affect me much, but I think I will probably name my methods with that in mind. For instance, where I would have normally called a method, IfValueIsZero_ReturnZero, here I think I would name it, testForValueZero_ReturnsZero. Taking that leading test into account and trying to make the the name read using test with the rest of the name.

First thing I work on is to make sure my object is initialized. Interestingly I find out that you can't really create an object that is derived from NSManagedObject without giving it a context. It must be using that context to create the object, even given that I have generated subclass files that contain the properties associated to that subclass, the object can't be initialized.

Given that I don't want my tests to be tied to the Data side of the Data Objects, I want to put my logic in a location that can be accessed without knowledge of the Model or Data Context. In VB I would create a Shared, or Static, function to do the work and give it the parameters it needed to perform the logic needed. Looking into how to create a Static method led me to another interesting discovery. To mark a method as Static you use the + symbol before the return type, and to make is not Static, you use the - symbol. I had seen those and had assumed to this point that + was for a public and - for a private method. Instead I find out that + can be used without an instance of an object and - need to have an instance before it can be called. Does that mean there is no notion of public and private function, or have I just not discovered how to mark methods for that yet?

After talking with my coworker, David, he explained to me how to make a method/property/variable public or private. If you add the declaration in the header, .H, file then it is public. You can define them in the implementation, .M, file and then they will be private. This starts to make sense as you are only importing the header file into other files, so they would only know about what they can see in the header file.

David also expanded upon using a Category for a class. It turns out to be very much like a partial class in .NET. The Category, adding to a class by defining the Category name after the interface name in a separate file. Then using the ClassName+CategoryName as a means of asking for that new interface. When you are using Categories, you only need to import the Category header file as it will bring along with it the base class information. Once you have imported that header file you get access to all public methods of the base class and the Category. Then at compile time, just like a partial class, the base class and Category get compiled together and are treated as 1 Class.

Getting back to the Tests. For my first test I want to compare 2 dates. I start out with the simplest thing I can think of, Is one Date object equal to the same Date object? There is a method for comparing Dates in objective c, named compare. So I create a new Date object and pass it into my method in both parameter places. I assert that the result returned in True. In my method I use that compare function and return the results. It works, as you would expect it would. Next I choose to test a Date from January to a Date in May. Assert that my function returns false, and of course it fails. Wait What? How on earth can something this simple fail? I assume that it is likely due to my knowledge of Obj-C, but at least I created a test and made sure that the logic I am using does what I want it to do before just blindly writing my app. If I had done that, I would be stuck trying to debug the app, wondering why things were not working as expected. Now I know before I get to that point, that there is a flaw in my logic that I need to address before moving on.

I have been reading, Test Driven Development: By Example , by Kent Beck. It is a fantastic book if you are interested in TDD. It has been very inspirational in that I always want to strive to improve how I am Testing when I read it. It is also very educational. One trick that I learned from reading it, something that I was not previously doing, is to leave a programming session with a failing test. This may seem counterintuitive at first, but his reasoning makes a ton of sense. If you leave your project with all passing tests, then when you come back to it, you will likely have to spend time remembering what you were doing and get your mind back to where you were when you left. If however, you leave a failing test behind, then when you return to your project you can run your tests, find the failing test, and know exactly where you were at. You will be able to jump right back in to your code and continue on from there.

Given this advice, I am going to leave my project with this failing test, and come back to it next time. I will know that my expectation of Date compare was wrong, and will be able to set about finding out where my logic is failing and what to do about fixing it.

Comments

Popular posts from this blog

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 fil…

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 CodeSchool, 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 goal a…