• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Test driven development - Zombie proof your code
 

Test driven development - Zombie proof your code

on

  • 394 views

Changing Legacy code can cause it to come back to life and bite you in the APP! Learn the symptoms and techniques to write testable code

Changing Legacy code can cause it to come back to life and bite you in the APP! Learn the symptoms and techniques to write testable code

Statistics

Views

Total Views
394
Views on SlideShare
394
Embed Views
0

Actions

Likes
1
Downloads
2
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Test driven development - Zombie proof your code Test driven development - Zombie proof your code Presentation Transcript

    • Test Driven Development Zombie proof your code
    • Pascal Larocque ● ● ● ● ● ● ● TrustCharge Team Behat guy Testing guy SOLID guy Pattern guy Father of 3 Star Wars Geek @pascallarocque
    • Why do we write code? ● Add New Features ● Maintaining old features
    • What are the challenges? ● I can’t understand what the code does ● Only the original programmer understands what it does… He’s not with us anymore ● Fixing a Bug creates a NEW BUG ● There is no documentation ● It’s Only working on my local ● We can’t upgrade because all are code is dependent on this version ● The only way to test is with the real data on production ● I have to test this manually
    • What are we really saying? “I’m Scared...When I change something, some other feature might stop working”
    • YOU’VE CREATED ZOMBIE CODE
    • How to survive the Zombie apocalypse 1. Write TESTS! 2. Write TESTABLE CODE
    • The Power of Testable code ● ● ● ● ● ● ● ● ● ● Forces Simplification of the code Simplifies Design Documentation of the code Less time debugging New code doesn’t break old code Refactoring becomes easier Interfaces are better designed Easier to do code reviews Fearless programming Faster than writing code without tests
    • How to write testable code PHPUnit Database Testing Legacy code testing PHPspec
    • Why aren’t we testing? ● ● ● ● ● ● ● ● Testing main flow is enough The code is legacy, impossible to test Don’t have time to test Fix bug first then write a test To be on the safe side manual testing is mandatory No one else is writing tests Testing and maintaining tests will cost more time After changing code, I have to change a bunch of test
    • Sorry to say this but...
    • WRONG DESIGN MISSING PROFESSIONALISM DON’T BLAME TESTING! LOSING DISCIPLINE NO-TEST DEVELOPMENT INEXPERIENCED DEVELOPERS UNREVIEWED CODE
    • “THE SECRET TO TESTING IS WRITING TESTABLE CODE”
    • HOW TO GET STARTED? “If the answer is not obvious, or if the tests looks like the tests would be ugly or had to write, then take that as a warning signal. Your design probably needs to modified; change things around until the code is easy to test, and your design will end up being better for the effort”
    • How can you tell if your code isn’t going to come back from the SVN and BYTE you in the APP? Look for the following SYMPTOMS.
    • SYMPTOMS - CONSTRUCTOR DOES TOO MUCH ● ● ● ● ● ● Using the NEW keyword in the constructor STATIC METHOD calls Anything more than field assignment Object not fully initialized after constructor CONTROL FLOW (conditions or loops) in constructor Constructor build complex Collections instead of using FACTORY or BUILDER ● There is an INITIALIZE block ● Not asking for Objects, looking for Objects (DEPENDENCIES in constructor)
    • SYMPTOMS - Digging into dependencies ● Object passed are used to access other objects ● LAW OF DEMETER VIOLATION: Method call chain with more than one -> ● SUSPICIOUS NAMES: Manager, Context, Registry, Container ● Creating mocks that return MOCKS ● Deceitful API (Real Dependencies are unclear) ● Too many “Middle Men” objects ● Needle in a haystack (due to breaking demeter law)
    • SYMPTOMS - Singletons & Global state (the dark side) ● ● ● ● ● ● ● ● Using SINGLETONS Accessing GLOBAL STATE STATICALLY Using STATIC FIELDS or STATIC METHODS Using a STATIC INITIALIZATION block Using a REGISTRIES NOT (or MIS-) using DEPENDENCY INJECTION Hard Coded Dependencies You have to read EVERY LINE OF CODE to understand the potential side effects
    • CURE USE DEPENDENCY INJECTION Replace your static method Wrap static method from third party libraries If you can’t wrap them, write adapters
    • SYMPTOMS - Object does too much ● When you have to use the word “AND” to describe what the Object does ● Object is hard to read for team members ● Object have fields that are only used in some methods ● Object has static methods that only operate on parameters ● MANY collaborators that you need to reach into for more collaborators ● HIDDEN INTERACTIONS behind public methods
    • CURE SOLID Single Responsibility Open/Close Principle Liskov Substitution Principle Interface Segregation Dependency Inversion
    • Tests should... ● Run Without ○ Network connection ○ Production Data ○ External API ● Run Fast ○ ~milliseconds ● Must ○ be Easy to maintain ○ run before every commit
    • Rules for TDD 1. Devise possible tests 2. Implement 1 FAILING test 3. Implement just enough code to PASS the test 4. Refactor code and clean up design 5. Repeat until ALL tests are passed THINK DIFFERENTLY TEST DESIGN IMPLEMENT TEST
    • How to write testable code PHPUnit Database Testing Legacy code testing PHPspec
    • PHPUnit - Installation ● ● ● ● Pear Phar Ubuntu package Composer Optional Packages ● Selenium ● DbUnit ● SkeletonGenerator
    • PHPUnit - Bootstrap ● Common Initialization of testing Environment $baseDir = realpath(__DIR__.'/..'); require_once $baseDir. '/tc_platform/Include/minimalBootstrap.php'; require_once $baseDir . '/TrustChargeLibrairies/vendor/autoload.php'; require_once $baseDir . '/PHPLibs/vendor/autoload.php';
    • PHPUnit - Writing Test ● Use the skeleton generator (should be in Eclipse) phpunit-skelgen --bootstrap bootstrap.php --test -- Class_Something Lib/Class/Something.php Class_SomethingTest Tests/Lib/Class/SomethingTest.php ● Write it yourself class Class_SomethingTest extends PHPUnit_Framework_TestCase
    • PHPUnit - Setup ● ● ● setUpBeforeClass() - Executed before class is instantiated ○ Setup DB ○ Setup Files setUp() - Executed before every test ○ Reset DB ○ Load Extra fixtures tearDown() - Executed after Test ○ Clean up DB ○ Remove Files
    • Depends @depends - For tests that depend on output from other tests
    • DataProvider @dataProvider - To test the same function with multiple values
    • Stubs and Mocks Stubs - Test double that allows you to control the flow of data Mock - Test double that allows you to control the flow of data and that assert that the object was called in a specific way
    • Test Doubles Doubles - When you cannot replace a static dependency you can preload a test doubles instead
    • Test Doubles Doubles - When you cannot replace a static dependency you can preload a test doubles instead Run in own process Preload Test Doubles
    • How to write testable code PHPUnit Database Testing Legacy code testing PHPspec
    • Database testing ● ● ● ● Must be fast Need to control the data in the database Must be ran in TESTING environment Clean up after yourself
    • 1. Setup - DB Connection Make sure you’re using TEST DB Use MYISAM to bypass foreign key issues Create the tables
    • 2. Setup - Fixtures Load Data Export Data
    • 3. Tests
    • Hard coded dependencies Hard coded DB name will cause you to truncate production DB instead of TEST DB
    • CURE Create new test double interface
    • How to write testable code PHPUnit Database Testing Legacy code testing PHPspec
    • "Behavior is the most important thing about software. It is what users depends on. Users like it when we add behavior, but if we change or remove behavior they depend on, they stop trusting us."
    • Legacy Code Change Algorithm 1. 2. 3. 4. 5. Identify the change points Find test points Break Dependencies Write Tests Makes changes and refactor
    • Identify test point Find the code you need to change Find test points
    • Bridge Class ● Class that bridges the gap between legacy code and new architecture ● Allows you to test in isolation ● Helps refactor out dependencies
    • Extract Method Extract 535 Lines of code
    • Bridge
    • How to write testable code PHPUnit Database Testing Legacy code testing PHPspec
    • PHPSpec ● http://www.phpspec.net While PHPUnit focuses on testing the functions and methods of the classes used to develop features, specBDD focuses on testing the behaviors of these classes. “ describing the code before you actually write it is a fear management technique. You don’t have to write all the code, just the spec of the next thing you want to work on. ” -- Kent Beck
    • Demo
    • It’s not worth writing test unless you have CONTINUOUS INTEGRATION I ZOMBIES
    • The broken window Theory Don't leave "broken windows" (bad designs, wrong decisions, or poor code) unrepaired. Fix each one as soon as it is discovered. Take some action to prevent further damage and to show that you're on top of the situation. We've seen clean, functional systems deteriorate pretty quickly once builds start breaking. There are other factors that can contribute to software rot, but neglect accelerates the rot faster than any other factor.