An All-Testing Day: Rolling My Own Mocks
After spending almost all of Wednesday reading, yesterday was a day spent entirely coding- and specifically writing tests for a class that I wasn’t sure how to properly test before. This specific class runs my main game loop (that plays until there is a win or draw), so it interacts with the board, with the UI and with the AI. I had initially written some tests for the way it interacted with the board by just hardcoding the expected values in to my tests. i.e. “if the Game class sends a human move to the board then that specific spot should equal an ‘x’”. However, this definitely didn’t feel right as now my test was coupling too many classes together. Plus, when it came to the interactions with the UI I couldn’t quite figure out how I was going to test the input that a method was supposed to receive from the command line, or that the command line would output a message.
Mike had me defer testing these things until I’d refactored my Game class according to my understanding of the SOLID principles, and since I’d managed to do that earlier in the week it was time to write some proper tests. By using “Mock” UI, AI and Board classes I could properly test my Game class, because the actions that those other classes took weren’t really what I wanted to test, what I wanted to test was just that my Game class was delegating properly. Testing frameworks, such as Rspec, provide a lot of help creating mocks to use in your tests, but Mike wanted me to spend the day rolling my own mocks so that I could get a clearer understanding of how they work. I was a little nervous about how well I’d be able to grasp the concept, but after reading these three articles on Wednesday and talking through with Mike how I planned to tackle the mocks- it really wasn’t bad at all. There were a couple places that I got hung up (testing recursion and some flow control), but all in all it felt like a really productive day. Between the tests and the mocks I wrote a few hundred lines of code and I just have one more “until” loop left to test. Hopefully I’ll finish that up this morning and then go through my other classes to see if and where I need to use mocks.
There was one other big lesson that I kept learning during my all-testing day too. Although I don’t think I could have test-driven my initial solution on how to run the game, it definitely would have been easier to write all these tests as I did my first big refactor instead of writing tests after the fact. (The right thing to do would have actually been to throw away my initial code and then TDD the second run at it). I think that during those initial “figuring-out” phases I was thinking way more about the edge cases that I would want to write tests for, and it also would have led to much cleaner code. As I was writing my tests yesterday there were several places that I decided to change up my initial code because the tests revealed where it was either too fragile or too rigid. Once again, TDD FTW.