Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Test Your Legacy Code
Search
Noel Rappin
November 07, 2011
Technology
3
190
Test Your Legacy Code
Presented at RubyMidwest, November 2011
Noel Rappin
November 07, 2011
Tweet
Share
More Decks by Noel Rappin
See All by Noel Rappin
Rails on Ruby: How Ruby Makes Rails Great
noelrap
0
280
In Defense of Metaprogramming
noelrap
0
350
Rails 7 Front End Tooling
noelrap
1
460
More Engineers, More Problems: Solutions for Big Teams
noelrap
0
160
The Rails 6 Front End: Building with Webpacker and Stimulus
noelrap
3
1.1k
The Developer's Toolkit
noelrap
0
140
High Cost Tests and High Value Tests: GOTO Chicago 2018
noelrap
2
130
High Cost Tests and High Value Tests
noelrap
1
140
The Road To Legacy is Paved With Good Intentions
noelrap
1
150
Other Decks in Technology
See All in Technology
XRミーティング 2024-03-20
1ftseabass
PRO
0
100
これまでのキャリアとこれからMLエンジニアとしてどう動くか
masatakashiwagi
1
790
2023 Japan AWS Jr.Championsに選出されての振り返りとこれから
hiropy877
1
130
現実世界の事象から学ぶSOLID原則
h0r15h0
25
11k
初心者が行く!サーバレスWebアプリ開発の道
nagaharutogawa
0
460
10分でわかるfreeeのQA
freee
0
260
OpenTelemetry実践 はじめの一歩
taxin
0
330
長文から長文を生成するLLMツールをオープンソースで作ってみた。
tomohisa
2
150
Introducing Pkl
enomotok
0
330
「XX試験の環境作ってよ」と言われた時によく使うAWSのソリューションについて
bun913
0
120
OCI Data Integration技術情報 / ocidi_technical_jp
oracle4engineer
PRO
1
1.5k
KubeCon EU: Unlocking new Platform Experiences with Open Interfaces
salaboy
1
380
Featured
See All Featured
Designing with Data
zakiwarfel
94
4.8k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
657
120k
Bash Introduction
62gerente
604
210k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
352
28k
Debugging Ruby Performance
tmm1
68
11k
The Straight Up "How To Draw Better" Workshop
denniskardys
227
130k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
18
1.7k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
12
1.4k
Mobile First: as difficult as doing things right
swwweet
215
8.5k
jQuery: Nuts, Bolts and Bling
dougneiner
57
7.1k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
242
20k
RailsConf 2023
tenderlove
0
510
Transcript
Test Your Legacy Code Noel Rappin @noelrap Monday, November 7,
11
You are handed a “rescue” project Monday, November 7, 11
Oh. My. God. The last person to work on this
was an idiot Monday, November 7, 11
Now what? Monday, November 7, 11
Shake your fists at the heavens for one minute. Photo
by Sha Sha Chu http://www.flickr.com/photos/shashachu/88654315/ Monday, November 7, 11
Get back to work. Monday, November 7, 11
What is a legacy application? Monday, November 7, 11
Code without tests Monday, November 7, 11
Code based on lost requirements Monday, November 7, 11
You don’t know what “correct” means Monday, November 7, 11
What’s your goal? Monday, November 7, 11
Respect working code. Do no harm. Monday, November 7, 11
Deliver features Monday, November 7, 11
At a sustainable pace Monday, November 7, 11
Improve code quality Monday, November 7, 11
The Boy Scout Rule Monday, November 7, 11
Our rescue project needs to change Monday, November 7, 11
Goofus and Gallant Monday, November 7, 11
“First, let’s write tests and cover the whole app” Monday,
November 7, 11
“That change is easy, I’ll just drop that in” Monday,
November 7, 11
They are both Goofus Monday, November 7, 11
Why not cover the whole app in tests? Monday, November
7, 11
“It’s a small world, but I wouldn’t want to paint
it” Monday, November 7, 11
It’s not a quick win Monday, November 7, 11
You can introduce bugs Monday, November 7, 11
Why not just drop something in? Monday, November 7, 11
It sets a bad precedent Monday, November 7, 11
It doesn’t make anything better Monday, November 7, 11
What’s a Gallant Software Craftsman to do? Monday, November 7,
11
The basic TDD process... Monday, November 7, 11
...applied to new changes only Monday, November 7, 11
Red. Green. Refactor. Monday, November 7, 11
Over time, coverage and quality grow organically Monday, November 7,
11
Okay, it’s not that easy Monday, November 7, 11
Why not? Monday, November 7, 11
You don’t know what to test Monday, November 7, 11
It’s hard to isolate objects under test Monday, November 7,
11
A friendly reminder: git is your friend Monday, November 7,
11
Cucumber Photo by karenandbradmerson http://www.flickr.com/photos/karenandbrademerson/492770419 Monday, November 7, 11
Cucumber is independent of the code Monday, November 7, 11
Cucumber can cover a lot of the app quickly Monday,
November 7, 11
But... Monday, November 7, 11
Cucumber is slow Photo by matley0 http://www.flickr.com/photos/matley0/2973398121/ Monday, November 7,
11
And it’s not great at isolating where a problem is
Monday, November 7, 11
Test-Driven Exploration Monday, November 7, 11
It’s like TDD... with cheating Monday, November 7, 11
Red. Make it green. Refactor. Monday, November 7, 11
The code is source of truth Monday, November 7, 11
Mock Testing Monday, November 7, 11
Mocks are fast and allow unit testing Monday, November 7,
11
But they can be hard to set up Monday, November
7, 11
Isolation Monday, November 7, 11
Only touch existing methods to call your new methods Monday,
November 7, 11
def crazy_insane_method return clean_new_method if new_condition # all the old
ugly stuff end Monday, November 7, 11
Seams Photo by boogah http://www.flickr.com/photos/boogah/4541496/ Monday, November 7, 11
Default method arguments Monday, November 7, 11
def crazy_insane_method(arg, arg, new_arg = nil) # crazy insane stuff
# now with new stuff end Monday, November 7, 11
Changing behavior without touching code Monday, November 7, 11
Monday, November 7, 11
class TestPurchase < Purchase def bang # no-op end end
user.purchase << TestPurchase.new Monday, November 7, 11
class Purchase def bang # no-op end end Monday, November
7, 11
Singleton classes Monday, November 7, 11
x = Purchase.new x.def bang # no-op end Monday, November
7, 11
Duck Typing Photo by Andyofne http://www.flickr.com/photos/andyofne/3757051334/ Monday, November 7, 11
class TestPurchase def bang # no-op end end user.purchase <<
TestPurchase.new Monday, November 7, 11
Use a pebble Photo by Slideshow Bruce http://www.flickr.com/photos/springfieldhomer/39079430/ Monday, November
7, 11
class Pebble def initialize(name) @name = name end def method_missing(method_name,
*args) p "#{method_name}(#{args.join(", ")}) from #{caller_method}" self end end Monday, November 7, 11
def caller_method(depth = 1) parse_caller(caller(depth+1).first).last end def parse_caller(at) if /^(.+?):(\d+)(?::in
`(.*)')?/ =~ at file = Regexp.last_match[1] line = Regexp.last_match[2].to_i method = Regexp.last_match[3] [file, line, method] end Monday, November 7, 11
What about bad tests? Monday, November 7, 11
Make sure the suite runs Monday, November 7, 11
Tests are also code Monday, November 7, 11
The 5-minute rule Monday, November 7, 11
When to refactor Monday, November 7, 11
Simple refactors can be done at any time... Monday, November
7, 11
...as long as the tests are green Monday, November 7,
11
Especially if you can’t test without refactoring Monday, November 7,
11
More complex refactors should be tied to actual new requests
Monday, November 7, 11
And in conclusion... Monday, November 7, 11
Respect working code Monday, November 7, 11
Test at as high a level as you can Monday,
November 7, 11
Leave things better than you found them Monday, November 7,
11
Isolate code under test Monday, November 7, 11
Consider the cost of change against the cost of no
change Monday, November 7, 11
railsrx.com @noelrap Rails Test Prescriptions Rate: http://bit.ly/nrmwtest Monday, November 7,
11