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

Automation Testing of Legacy Applications

Automation Testing of Legacy Applications

Everyone loves to work on a greenfield project. You can choose language, architecture, design from scratch, all the new, shiny stuff. The reality is that software engineers at some point need to work on or support legacy applications. It’s alive because it has some business value. The code is so messed up (“I just need to add one more ‘if’ to this method”), and the whole thing is held together by spit and baling wire. There are no automated tests safety net. Every change requires manual tests and a prayer to the software gods.

This talk will show you how to start small and work your way up to the point where you reach a confident state. It will show you how to optimize for the team happiness. It will affect topics such as, unit testing, acceptance tests, static code analysis, continuous integration, architecture for testability. The talk is inspired by real life experience, working on three legacy projects in the span of more than five years.

emanuil

June 04, 2015
Tweet

More Decks by emanuil

Other Decks in Programming

Transcript

  1. AUTOMATION TESTING
    LEGACY APPLICATIONS
    @EmanuilSlavov
    OF

    View full-size slide

  2. Your application is legacy,
    if you don’t have automated tests.

    View full-size slide

  3. GREENFIELD PROJECT

    View full-size slide

  4. BROWNFIELD PROJECT
    BROWNFIELD PROJECT

    View full-size slide

  5. WHY INVEST IN LEGACY
    SYSTEM?
    TEAM HAPPINESS

    View full-size slide

  6. LOW TEAM MORALE

    View full-size slide

  7. Fragile Software
    Slow Feedback
    Stupid Errors
    Repetitive Work

    View full-size slide

  8. Quality software is team effort.

    View full-size slide

  9. WHAT TO DO ABOUT IT

    View full-size slide

  10. Start with basic acceptance tests

    View full-size slide

  11. Functionality that makes money
    Must have functionality - compliance, security
    Repeating Manual Tests - Save Time
    Pareto Principle - 80/20

    View full-size slide

  12. Do not test through the UI.
    (if possible)

    View full-size slide

  13. result = RestClient.post(
    REGISTER_URL,
    user_details.to_json,
    {:content_type => :json}
    )

    View full-size slide

  14. 800 test x 10 seconds = 2h 13min
    This saved us:

    View full-size slide

  15. Limit external dependencies calls.

    View full-size slide

  16. Need to Call
    External System
    Comes from
    automated
    test?
    Talk to the
    real system
    No
    Fake the
    response
    Yes

    View full-size slide

  17. Test should create the data they need.

    View full-size slide

  18. Scenario: Client admin should not be able to
    view master’s agencies
    Given а master user
    And master creates agency
    And a client admin
    When client admin views master's agency
    Then client admin should get an error

    View full-size slide

  19. Set test data via API or DB.

    View full-size slide

  20. Poll for results from API/DB operations.

    View full-size slide

  21. sleeping(1).seconds.between_tries.failing_after(10).tries do
    result = some_operation
    raise 'No Data' if result == []
    end

    View full-size slide

  22. Run a test 20 times consecutively.
    Commit only if the test does not fail.

    View full-size slide

  23. for i in {1..20}; do your_test; done

    View full-size slide

  24. Make async tasks sync

    View full-size slide

  25. CODE CHANGES

    View full-size slide

  26. First Order of Business:
    Remove Unused Code

    View full-size slide

  27. KNIGHT CAPITAL
    MELTDOWN
    LOST $440 MILLION
    IN 45 MINUTES

    View full-size slide

  28. Second Order of Business:
    Stop The Rot

    View full-size slide

  29. CONTINUOUS
    INTEGRATION

    View full-size slide

  30. Run on every commit
    Fast
    Hook one by one all the checks
    Run longer tests periodically

    View full-size slide

  31. Developers need to receive feedback
    about their new code within 5 minutes.

    View full-size slide

  32. WHAT CHECKS TO
    RUN ON COMMIT?

    View full-size slide

  33. The PHP Case

    View full-size slide

  34. php -l api/models/mobile_push_model.php
    PHP Parse error: api/models/mobile_push_model.php on line 61
    Errors parsing api/models/mobile_push_model.php
    Linter

    View full-size slide

  35. UnknownObjectMethod in file:
    api/models/mobile_push_model.php, line: 55, problem entry:
    $pusher->reallyUnsubscribeDevice
    ($params['user_id'], $params['device_id'], $actions)
    HHVM

    View full-size slide

  36. STATIC CODE QUALITY

    View full-size slide

  37. CYCLOMATIC COMPLEXITY
    function testPrint() {
    echo('Hello World');
    }
    Complexity: 1
    function testPrint($parameter) {
    if($parameter) {
    echo('Hello World');
    }
    }
    Complexity: 2

    View full-size slide

  38. Method complexity
    should be less than 10.

    View full-size slide

  39. 12 Fatalities
    $1,2 Billion Settlement

    View full-size slide

  40. ”The throttle angle function scored
    [complexity] over 100 (unmaintainable)”
    Michael Barr

    View full-size slide

  41. Complexity 82
    Complexity 10
    Constantly refactor
    to decrease complexity

    View full-size slide

  42. Method size should be less than
    100 lines (ideally less than 50).

    View full-size slide

  43. Improve the code - then lower the
    threshold on commit check.
    Then repeat.

    View full-size slide

  44. FIGHT LEGACY CODE
    WRITE UNIT TESTS

    View full-size slide

  45. Written by Developers
    Fast, Independent
    Test Technical Aspects
    Cooperation between QA & Developers

    View full-size slide

  46. 100% test coverage is not sufficient!

    View full-size slide

  47. SECURITY TESTS

    View full-size slide

  48. SQL Injection Detection
    (PHP and ADOdb)
    $dbConn->GetRow(“SELECT * FROM users WHERE id = $user_id”)
    $dbConn->GetRow(“SELECT * FROM users WHERE id = ?”, array(‘$user_id’))

    View full-size slide

  49. Those errors can be caught with code
    analysis.

    View full-size slide

  50. There was no such tool.
    So we developed one.

    View full-size slide

  51. github.com/emanuil/php-reaper

    View full-size slide

  52. Your second line of defense.

    View full-size slide

  53. Show a lot with TV and Raspberry Pi.

    View full-size slide

  54. Live Graphs + Deploys

    View full-size slide

  55. Аutomatе the most important functionalities
    Continuously improve static code quality
    Write unit tests for changed/new code
    Expand checks on commit
    Enable monitoring

    View full-size slide

  56. @EmanuilSlavov
    EmanuilSlavov.com

    View full-size slide