Wednesday, December 09, 2015
I lost my best friend today.
Since I was 17, my best friend has been the amazing cat that you see above the post. He's the best cat I've ever known. He was smart, brave, sweet, and a very good kitty. He was also very much daddy's guy. He was always there to greet me when I woke up in the morning and when I got home from work.
We've been through a lot together, we've taken care of each other, and we've always tried to be there for each other.
Unfortunately, today he passed away at the admirable age of 18. The vet was with us in hoping that he could make it much, much longer for a number of reasons, but it seems that that wasn't meant to be. Yesterday, we got word that he wasn't going to be around for much longer, so we did what we could – we bought him fried chicken (which he loved, but didn't often get because it wasn't very good for him), gave him his holiday gifts early and spent yesterday and today with him, showing him how loved he is. He ate a large amount of the chicken and enjoyed all of the cuddles.
We were both there for him when he passed away, petting and cuddling him while telling him what a good kitty he has always been and how much we love him. He's now having a well deserved rest and isn't suffering anymore. We laid him to rest next to Karyl's cat, Simba, who passed away a couple of years ago and whom he adored basically since he met her.
I will miss him greatly. Karyl and I both will, to be honest. The house will feel very empty without him in it.
To share our love for him with the world, at least a little bit, here are a few links involving him:
I will miss you very much, fuzzy buddy. You will always have a big place in my heart
Current mood: SadCurrent music: Craig Ferguson's series finale – Bang Your Drum
Sunday, August 30, 2015
TDD is a very useful tool. Done well, it offers assurance that your code does what it is supposed to do, provides a set of baked in regression tests, allows you to refactor code without worrying that you will break something in the process and acts as a sort of living design document.
It is not, however, a silver bullet. If done poorly, it can cause code to become rigid. This generally happens when people test the implementation details rather than the behavior. In a language like Python, where there are no truly private methods, it can be even easier to test implementation rather than behavior if you aren't cautious. I'll also say that it can be really difficult to effectively test Android code because TDD isn't a first class citizen in that ecosystem.
In my opinion, the possible downsides of TDD are generally far outweighed by the bonuses – especially since the downsides are usually able to be mitigated by exercising some self-discipline.
That's not to say that every piece of code you ever write has to be done with TDD. There are some small, usually one-liner style programs, that I write which I don't test drive. If I'm going to be using something once and tossing it, provided that there isn't really a danger of permanent damage if the code doesn't do what I want the first time, I may decide that it isn't worth the effort to set up a testing harness.
Now that we've got my opinions on the topic out of the way, I have to say that I don't get the hate that some developers have for TDD. I can understand a non-technical manager not understanding how writing tests (more code) isn't a drawback, but people who write software for a living are another story.
If I had to guess, I'd say it was probably some combination of fear of the unknown, a previous bad experience (whether because of lackluster tools, lack of guidance, or inexperience), or posturing on the part of the developer (after all, we are often not known for a lack of ego).
There are occasionally reasons to not test something (few and far between), but as a general rule, having the tests will only help you now as well as helping future you when you have to dig back into the code in 6 months. Not wanting all of the tools that could help you is just crazy.
This whole post was inspired by a tweet that a friend of mine re-tweeted (and its associated tweets), so let's take a little time to critique the conversation.
Shocked by the number of jobs proposed to me whose ads list "TDD" as a requirement. Are we really still doing this?— Bodil Stokke (@bodil) August 30, 2015
Yes. Because it works. I've already covered that above, so I'm not going to repeat myself.
TDD works really well for a lot of people, and that's great. Others have different ways of thinking about programming. Don't exclude them!— Bodil Stokke (@bodil) August 30, 2015
If you are working in a shop that doesn't do test driving (I'd be tempted to ask why not, but just for the sake of argument), then yes, a person who doesn't do TDD will be fine. If you are in a shop that does TDD and the person is willing and able to learn TDD, then consider helping them get up to speed. If they refuse, then they're probably not a good fit for your team/company. Sorry, but that's the way it is.
If your team all does TDD, but one person refuses to do so, you lose a lot of the benefits. The baked in set of regression tests is no longer complete. The living documentation is no longer complete. Refactoring becomes trickier. Bugs can become harder to track down. These are problems.
@makmanalp @jasonpbecker Yes, I think this is a matter of individual neurology. My architectures definitely get _less_ simple with TDD.— Bodil Stokke (@bodil) August 30, 2015
Then you're probably doing TDD wrong. In all likelihood, you are testing implementation instead of behavior. This is actually a pretty common mistake for people who aren't used to TDD and it takes some experience to get over. Heck, even people who have been doing it for a while can slip up sometimes. None of us are perfect. That doesn't change the fact that you're probably using the tool wrong.
@makmanalp @jasonpbecker If I'm TDDing with unit tests, it helps me a lot. If I'm TDDing with integration tests, I lose the big picture.— Bodil Stokke (@bodil) August 30, 2015
You don't TDD with Integration Tests, or at least not only with integration tests. You use Unit Tests to test functions (given input, check output for example). Integration Tests are used to test a series of Units (kind of like checking to see that a bunch of legos you put together actually build a wall).
@jasonpbecker TDD literally gets in the way of my thinking properly about my code in some cases.— Bodil Stokke (@bodil) August 30, 2015
Then you're looking at it wrong. Each unit test should be a condition that your function should fulfil. You only test the criteria that your code is supposed to fulfill. That's not to say that you can't spike out something you're not sure of (especially if you're working with a new language), but before that code actually makes it into your codebase, it needs to be under test, and that test needs to fail first.
@jasonpbecker In my case, striving to always do TDD would have a negative impact on the quality of my code.— Bodil Stokke (@bodil) August 30, 2015
I can sort of get behind this for one very simple reason – some things are just ridiculously difficult (if not damned near impossible) to test. These cases don't come up often, but they do occasionally come up. Other than that, test your code. For everyone's sake.
@MaggieL "You must know what TDD is" is still a bad requirement. And no, "we do TDD here and so will you" is something I get a lot.— Bodil Stokke (@bodil) August 30, 2015
I disagree. If the entire team (or company) does TDD, then yes, it is a valid requirement for the job. If you refuse to use TDD, then you don't have a place on the team for reasons that I've already outlined. In fact, I'm glad more places are making it a requirement (provided that their people write good tests).
The sad thing is that I hear these sorts of arguments a lot. Thankfully, however, I seem to be hearing them less lately. I honestly welcome constructive criticism of practices because it helps people grow. You need to be prepared to have others respond to that criticism though.
Just complaining about a methodology you don't like without valid reasons doesn't help anyone (and that's exactly what that last tweet was).
Current mood: Calm
Current music: INXS – The Stairs
Friday, April 24, 2015
I've recently started learning how to write apps for the Android platform and, since the company I work for does all of our development in a Test Driven (TDD) fashion, I'm writing my first app using the same methodologies.
Unfortunately, the Android platform apparently wasn't designed with TDD in mind. Automated Unit and UI testing currently seem to be second class citizens because there isn't a lot of good information on testing in android. There are now decent tools, but not a lot of documentation on how to use them or avoid pitfalls.
I think it's time that we work to improve that shortcoming, so my plan is to walk you through the process of creating an app from scratch while pointing out the pitfalls and gotchas that I come across on the way so you will have a better chance of avoiding them. This entry represents the end result of my Sprint 0 (setup) phase for the app. It took about a week and a half of going through online documentation and talking with co-workers to get to this point. With this, you should be able to do it in an afternoon.
Pocket Bartender. This should be a relatively simple app since it's just going to be a fairly basic CRUD app. It will take a drink name or ingredient and give you a recipe or list of recipes for that drink or the drinks that use that ingredient. I'll also probably add functionality to favorite and hide drinks.
Phone: Samsung Galaxy s5 (sprint) running Android 5.0 (Lollipop)
Tablet: Samsung Galaxy Tab 4 (sprint) running Android 4.4.2 (KitKat)
IDE: Android Studio 1.0.1
Emulator (phone): Nexus 5 API 21 x86
Before you start, you'll need to have the Java 1.8 JDK installed and configured properly since coding for Android is done in Java (I am told that Groovy also works, but I haven't looked into seeing what's required to be able to code for Android in it).
Next, you'l want to install Android Studio. Since I was working through the Udacity Android course before starting this project, I had Android Studio installed already.
Run the Android SDK Manager (Tools > Android > SDK Manager) and install the following packages:
These two packages will be required by the tools we'll install later.
Now that your IDE is installed, you'll need to enable developer mode on your phone and/or tablet (assuming that you want to test on hardware as well as in the emulator). How to do this may vary by phone maker/model, so I'll leave that portion of the exercise to you. It should just take a quick google search.
When you have enabled Developer Mode, go into Settings > Developer Options and make the following changes:
USB Debugging – ENABLED
Window Animation Scale – OFF
Transition Animation Scale – OFF
Animator Duration Scale – OFF
According to documentation, the last three settings can be manipulated via code, but it's easier to just turn them off in the Developer Options menu.
Open Android Studio and make a dummy project with a blank activity. We will be using this project later, so don't delete it after you're done with this step. When the project is created, follow the directions outlined in Step 3 under “Setting up a Device for Development” to set up your phone to be able to receive files from Studio. The steps required to do this vary by operating system.
When you plug your phone into your computer, it may not immediately show the dialog asking if you want to allow your phone to communicate via USB. If you don't see the window, don't worry. Just lock and unlock your phone a couple of times until it gives you the dialog.
You'll need to do this for each device you want to connect to your computer.
I've been told by one of my co-workers that his phone occasionally disables USB Debugging, so if you are having problems transferring your program from Android Studio to your phone or tablet, make sure the setting is enabled. Also, Android Studio occasionally fails to load the program properly, so you may just have to make sure the program is uninstalled on your phone and re-try (this happens to me on a somewhat regular basis).
Robolectric and Espresso:
While you can write unit tests for android in JUnit, the tests tend to run pretty slowly. Robolectric is considerably faster. Additionally, you can run UI tests using Espresso. Getting this set up manually is not a trivial task, but thankfully there is a project on github that will help alleviate a lot of the pain.
Download the Deckard project and follow the instructions on the page in order to get the project imported into Android Studio. The Deckard project comes with a Robolectric test file and an Espresso test file, both of which should run from the IDE as well as the command line. You may need to plug your phone into your computer in order to get the Espresso tests to run from the command line.
If you've ever done android development before, you will notice that the Deckard project is missing a lot of things. It is literally about as bare bones as a TDD android project can be and still function. We'll be fixing that later, but for now, what we have is fine.
Go ahead and change your package names to something that makes sense for your project and make sure the tests still pass. Just make sure that everything is in the same package.
At this point, the screen you get on your phone should look like this:
Dagger is a dependency injection (DI) tool for android. According to all accounts, it is considerably faster than Roboguice (which was being used heavily before).
Setting up Dagger is fairly simple. Open your build.gradle file and, make it look like this version from my git repo.
Most of the changes are pretty self explanatory since they're just adding gradle entries for dagger and dagger-compiler. However, there are a couple of changes that require a little explanation.
compile 'com.squareup:javawriter:2.5.0' is used in order to resolve a dependency conflict between Dagger and Espresso. Both tools use javawriter, but they call for different versions. This, along with the exclude calls in dagger, dagger-compiler, and espresso-core forces the application to use a version that works with both.
At this point, most of the main tools for doing TDD in android are installed. We'll probably install Mockito for using mocks later, but we don't need it right now, so we'll do that when it comes up.
Before we write our first code example of DI with Dagger, let's make a small change to the app in order to convince ourselves that it's really working (this will be the basis of the code we're injecting in a minute, so bear with me).
Open DeckardActivity.java and add the following lines to onCreate:
TextView t = new TextView(this);
t = (TextView)findViewById(R.id.text);
Running your Espresso tests should now cause them to fail (that's a good sign in this case). Open DeckardEspressoTest.java and change the .check(matches()) statement to look for “foo” instead of “Hello Espresso”, run the tests to make sure they pass and then run the application in either your emulator or phone. The resulting screen should look like this:
Now that we know that we can change the message on the screen programmatically and the UI tests will still pass with the new string on the screen, we can write our first DI module. Make a Foo interface file as well as a FooObject class file with the contents of the files linked to on my github account. This is what we will be injecting.
You'll also need to make a module file in order to handle the actual injection. In this case, the file is DummyModule. Go ahead and copy the contents of the file from my github. Note that the injects line states the classes that the module will be injected into.
Open your DeckardApplication.java file and make the changes needed to make it look like the linked file on my github. At this point, I need to point out a couple of things that will save you future headaches.
First, while you can build the ObjectGraph by using DummyModule as an argument directly, I am told that you will want to build it using the getModules method for ease of testing later.
Second, in this example, getModules returns a List of type DummyModule. If you are using more than one module, it will return a List of type Object. Logically speaking, you should be able to make the example in this file return a List of type Object, but if you try, you get the incredibly weird error that your program can't cast type DummyModule as type Object (which makes no sense considering that, as a class, DummyModule inherits from Object). I have no idea why this is the case, but it is.
Now for the step that brings together everything we've done so far. Alter your DeckardActivity to look like the one linked to in my github repo. The changes from the last time that we touched the file (to make the screen read “foo”) are using @Inject to inject an instance of FooObject, to set a string equal to fooObject's provideText return value and to set the text on the screen equal to that string.
Your Espresso test should now be red. You'll need to change the DeckardEspressoTest.java file to check for “injected foo” instead of “foo” in order to make it green again.
Now, if everything works the way it should, your tests will pass and, when you run the program on either your phone or in the emulator, you should see the following:
You're now set up to do TDD in android (minus the mocking tools, which we'll get to later). The program as it stands needs a great deal of work to get where we're going, but we're off to a good start.
In the next entry in this series, we'll start Sprint 1 tasks.
Current mood: Even
Current music: The Guess Who – No Time