01 apr
New week, new testing fails!
Here are the tabs I left open from last week:
- Stack overflow: Can unit testing be successfully added to an existing project?
- Writing unit tests for existing JavaScript
-
Comprehensive guide to unit testing in AngularJS
- There are many of these types out there, but this is the only one that goes step-by-step about the whys/hows of testing factories and other services that depend on factories
- Angular ngMock
$inject
docs
I’ll read some of that and see where it takes me.
More reading, more youtubes. I watched some legacy codebase talks that sent me down the path of looking at end-to-end testing instead of unit testing. Since a legacy codebase has so much going on, unit testing can be very difficult, especially for figuring out where to start. Starting with E2E tests gives you test coverage of an app’s behavior, so when you go back and start refactoring/adding unit tests, you can maintain that behavior without screwing things up too much. At least, that’s the idea I’m getting with all this.
SO. Even though I’ve spent a lot of time trying to set up jasmine/karma, I’m going to pivot to trying out cypress. I’ll add a new branch to the repo and begin anew! If it turns to be too much of headache, then I’m not really sure what I’ll do after that. But I also have a copy of Michael Feathers’ Working Effectively with Legacy Code, so maybe I’ll have a better roadmap later this week. I guess we’ll wait and see what happens!
02 apr
Time to get Cypress.io set up.
Setting up cypress was very easy! I got the hours app demo up and running basics tests very quickly, which was a pleasant surprise. Now… what to test?
After some additional youtube watching and article reading, this seems to be the consensus on E2E tests:
E2E workflow
- Build user functions
- list the features of the system and their interconnected components
- list input data, action, and output data for each feature/function
- identify relationships between functions
- determine whether function can be reusable or independent
- Build conditions based on user functions
- build a set of conditions for each defined (above) user function
- conditions include sequence of events, timing, data
- examples: invalid UN/PW, PW strength checks, error message for invalid options, etc.
- Build test scenario
- at least one per user function
- definitely more if there are multiple conditions per function/feature
I always have a hard time deciding where to start, and several articles suggested focusing on the most important tasks. What are the most important tasks of the hours app?
- listing hours for each library
- open/closing soon/closed/opening soon status listing
- calendar browsing
03 apr
The Legacy Code book came yesterday! I’m going to spend a good amount of time today reading through it and taking notes. Yippee!
I’ll write up my notes here, but before I forget, this article on stubbing HTTP requests with sinon looks very, very useful for the future.
preface
- Legacy code is code that we’ve gotten from someone else… essentially, somebody else’s code
- Often used as slang term for difficult-to-change code that we don’t understand
- But really: code without tests
- This book gives techniques that you can use to understand code, get it under test, refactor it, and add features
ch 1: changing software
- Four reasons to change software:
- adding a feature
- fixing a bug
- it’s hard to distinguish the difference between these two
- improving the design
- optimizing resource usage
ch 2: working with feedback
- Two options when changing code: “edit & pray” vs. “cover & modify”
- A test is not a unit test if:
- it talks to a database
- it communicates across a network
- it touches the file system
- you have to do special things to your environment (edit config file) to run it
- When functions depend directly on things that are hard to use in a test, they are hard to modify and hard to work with (my main issue, presently)
- Legacy code catch 22: when we change code, we should have tests in place, but to put tests in place, we often have to change code
- Legacy code change algorithm:
- Identify change points
- Find test points
- Break dependencies
- Write tests
- Make changes and refactor
- the goal is make functional changes that deliver value while bringing more of the system under test
- at the end of each programming episode, we should be able to point not only to code that provides some new feature but also its tests
ch 3: sensing and separation
- Lots of object-oriented examples in this chapter, was referred to ch. 19 for functional examples of fakes/mocks
ch 4: the seam model
- A seam is a place where you can alter behavior in your program without editing that place
- [This chapter is pretty essential, but I’m struggling to understand without JS examples]
04 apr
More from the Legacy Code book today.
ch. 19: My project is not object-oriented, how do I make safe changes?
- “Sometimes a function calls a function that calls another function. Then it calls something hard to deal with: a function that actually does I/O someplace or comes from some vendor’s library. We want to test what the code does, but too often the answer is ‘it does something cool, but only something outside the program will know about it, not you.’”
- my life right now
- Breaking dependencies will usually mean using a link seam (see page 36) and attempt to get larger areas of code under test
Based on what I’ve read so far, it’s going to be better for me to start with covering large areas of code and working my way to smaller bits of code. Broad => narrow, which means starting with end-to-end tests, moving down to integration, and finally working on unit tests of individual components like functions, controllers, directives, modules.
05 apr
Spent the morning setting up cypress and writing tests. It’s amazingly easy and so awesome to see tests running in the browser! I’m going to need to write tests for individual pieces of the app and for each page/view change, so it might take a while, but this is definitely going to be beneficial. I’ve already spotted some weird accessibility stuff by writing these tests, so it has already been worthwhile.
In the afternoon, I switched back and forth between testing and setting up my laptop. It was running Sierra, so upgrading it to Mojave took about 2 hours. Then pulling down my dotfiles and setting up all my apps and development environment took quite a bit of time (turns out my documentation wasn’t as solid as I thought it was!), so that was most of my afternoon. But now I can work from anywhere! Huzzah!