Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[RailsConf 2022] Testing legacy code when you dislike tests (and legacy code)

[RailsConf 2022] Testing legacy code when you dislike tests (and legacy code)

Are you supporting legacy code? Would you like to stop? A good testing strategy can transform legacy code into living code that is resilient and easy to evolve.

Learn why legacy code is so difficult to maintain and identify where tests can make the most impact. Not just any tests, though! We'll dive into the characteristics of high-value versus low-value tests and learn techniques for writing tests that minimize the cost of change.

Developers of any experience level can benefit from these concepts. Familiarity with Rails and an automated testing framework is helpful but not required.

Maeve Revels

May 19, 2022
Tweet

Other Decks in Programming

Transcript

  1. @maeverevels #RailsConf2022 Maeve Revels Testing Legacy Code When You Dislike

    Testing (and Legacy Code) betteroff.dev/railsconf-2022-testing-legacy-code
  2. @maeverevels #RailsConf2022 Agenda Questions that deserve answers • What is

    legacy code? • Why should we test it? • When should we test it? • What should we test? • How do we avoid legacy tests? • How do we write high-value tests?
  3. @maeverevels #RailsConf2022 Anonymous dev at your old job, probably Code

    originally written by someone else that is currently broken in production.
  4. @maeverevels #RailsConf2022 • 20 years of experience creating legacy code

    • Principal Software Engineer at • Platform team - infrastructure and scalability @maeverevels @maeve [email protected] Maeve Revels
  5. Support burden Cost Time @maeverevels #RailsConf2022 Go-to-market blog post Weekly

    email newsletter Social media campaign Call to action in application
  6. Cost of change Cost Time @maeverevels #RailsConf2022 Passed acceptance testing

    Tweaks based on feedback Changes for large customer
  7. Cost of change Cost Time @maeverevels #RailsConf2022 Passed acceptance testing

    Tweaks based on feedback Changes for large customer 🤞
  8. Cost of change Cost Time @maeverevels #RailsConf2022 Passed acceptance testing

    Tweaks based on feedback Changes for large customer Production incident 😱
  9. Cost of change Cost Time @maeverevels #RailsConf2022 Passed acceptance testing

    Tweaks based on feedback Changes for large customer Production incident Time to write tests…
  10. Cost of change Cost Time @maeverevels #RailsConf2022 Passed acceptance testing

    Tweaks based on feedback Changes for large customer Production incident PM wants new functionality
  11. @maeverevels #RailsConf2022 Gompertz growth model Time • Growth rate of

    organisms • Population dynamics • Market demand for new products • Adoption of new technology
  12. @maeverevels #RailsConf2022 A seam is a place where we can

    change behavior without changing code in that place
  13. @maeverevels #RailsConf2022 Sandi Metz, Practical Object-Oriented Design: An Agile Primer

    Using Ruby From a practical point of view, changeability is the only design metric that matters; code that's easy to change is well-designed.
  14. @maeverevels #RailsConf2022 Sandi Metz, Practical Object-Oriented Design: An Agile Primer

    Using Ruby Efficient tests prove that altered code continues to behave correctly without raising overall costs.
  15. @maeverevels #RailsConf2022 If it is easier to fix regressions than

    it is to fix the test, that test is not worth the effort
  16. @maeverevels #RailsConf2022 # Don't assert static counts expect(page).to have_content("4 requirements")

    # Get dynamic counts from the data layer instead expect(page).to have_content("#{feature.requirements.count} requirements")
  17. @maeverevels #RailsConf2022 # Avoid direct use of selector logic expect(page).to

    have_css(".card__field i.fa-flag[data- title='International expansion']")
  18. @maeverevels #RailsConf2022 # Avoid direct use of selector logic expect(page).to

    have_css(".card__field i.fa-flag[data- title='International expansion']") # Extract complex selectors into descriptive methods def have_goal_icon(goal_name) have_css(".card__field i.fa-flag[data-title='#{goal_name}']") end expect(page).to have_goal_icon("International expansion")
  19. @maeverevels #RailsConf2022 • Legacy code maximizes costs • Testing minimizes

    costs • Focus on behavior over inputs/outputs • Write high-value tests for high-value code