This document provides rules for applying test-driven development (TDD) to legacy code. It discusses:
- Using a bottom-up (inside-out) approach rather than top-down when working with legacy code.
- Only testing the modified code, not writing tests for all use cases of legacy code.
- Testing requirements of new code rather than all behaviors and use cases.
- Injecting new testable code into legacy code without changing it.
- Breaking hidden dependencies to decrease coupling and increase cohesion.
The document provides examples of applying each rule through code snippets from a sample e-commerce application. It aims to help structure new code for testability while minimizing changes to
Stopping the Rot - Putting Legacy C++ Under TestSeb Rose
The document discusses introducing unit testing to legacy C++ code. It covers choosing a testing framework, writing initial tests and mocks, and various refactoring techniques like wrapping dependencies, extracting components, and adding non-intrusive C seams to facilitate testing. The goal is to incrementally make the code more testable while maintaining functionality through practices like test-driven development.
You’re finally doing TDD, but your past mistakes are catching up with you. No matter what you do, you can’t get rid of the gaping black holes caused by your legacy code.
In this presentation, we learn about the causes of legacy code and the reasons it is so difficult to work with. Then we discuss various techniques to test untestable code, revive and simplify incomprehensible code, redesign stable yet untested code, and repair that rift we created in the time-space continuum.
This document discusses using GoogleTest as a C++ unit testing framework. It provides an overview of GoogleTest features such as assertion-rich testing, test fixtures, test result reporting, and parameterized/data-driven tests. It also demonstrates how to set up a sample project in Visual Studio to write and run tests using GoogleTest, including features like type assertions, death tests, and test filtering.
This document provides an overview and summary of Boost and Google Test (gtest). It discusses key Boost libraries like smart pointers, assign, foreach, and bind. It explains how Boost handles memory management and containers. It also covers the basics of gtest like writing assertions and test fixtures. The document recommends gtest as a lightweight unit testing framework compared to Cppunit.
Modern Testing provides concise summaries of key points from the document in 3 sentences:
The document discusses modern testing practices and frameworks for Python projects, emphasizing the importance of writing tests to ensure high quality software and outlining different types of tests like unit, integration, and acceptance tests. It presents examples of using the unittest and pytest frameworks for writing tests in Python as well as the Robot Framework for acceptance testing. The document concludes by advocating for adopting best practices like using tox for local test invocation and continuous integration to enforce testing standards.
Practical tips for dealing with projects involving legacy code. Covers investigating past projects, static analysis of existing code, and methods for changing legacy code.
Presented at PHP Benelux '10
The document discusses testing legacy Rails applications. It provides steps to get testing set up on a legacy Rails app, including creating a test database, running migrations, and getting Rake tasks to run tests. It emphasizes starting with one test at a time, finding and fixing bugs, and refactoring code. Examples are given of writing a model test based on application logs and fixing a failure by updating code. The document stresses treating methods as isolated boxes and only testing one thing at a time to incrementally add tests to a legacy codebase.
The document discusses mutation testing, a technique to evaluate test quality by automatically introducing faults ("mutants") into code and checking if tests can detect the faults. It introduces key concepts like mutants, mutation operators, and tools like PIT that make mutation testing practical. While previously limited by performance, modern tools like PIT can analyze large codebases in reasonable time. Mutation testing tests tests more rigorously than code coverage alone by checking tests can detect small code changes.
Stopping the Rot - Putting Legacy C++ Under TestSeb Rose
The document discusses introducing unit testing to legacy C++ code. It covers choosing a testing framework, writing initial tests and mocks, and various refactoring techniques like wrapping dependencies, extracting components, and adding non-intrusive C seams to facilitate testing. The goal is to incrementally make the code more testable while maintaining functionality through practices like test-driven development.
You’re finally doing TDD, but your past mistakes are catching up with you. No matter what you do, you can’t get rid of the gaping black holes caused by your legacy code.
In this presentation, we learn about the causes of legacy code and the reasons it is so difficult to work with. Then we discuss various techniques to test untestable code, revive and simplify incomprehensible code, redesign stable yet untested code, and repair that rift we created in the time-space continuum.
This document discusses using GoogleTest as a C++ unit testing framework. It provides an overview of GoogleTest features such as assertion-rich testing, test fixtures, test result reporting, and parameterized/data-driven tests. It also demonstrates how to set up a sample project in Visual Studio to write and run tests using GoogleTest, including features like type assertions, death tests, and test filtering.
This document provides an overview and summary of Boost and Google Test (gtest). It discusses key Boost libraries like smart pointers, assign, foreach, and bind. It explains how Boost handles memory management and containers. It also covers the basics of gtest like writing assertions and test fixtures. The document recommends gtest as a lightweight unit testing framework compared to Cppunit.
Modern Testing provides concise summaries of key points from the document in 3 sentences:
The document discusses modern testing practices and frameworks for Python projects, emphasizing the importance of writing tests to ensure high quality software and outlining different types of tests like unit, integration, and acceptance tests. It presents examples of using the unittest and pytest frameworks for writing tests in Python as well as the Robot Framework for acceptance testing. The document concludes by advocating for adopting best practices like using tox for local test invocation and continuous integration to enforce testing standards.
Practical tips for dealing with projects involving legacy code. Covers investigating past projects, static analysis of existing code, and methods for changing legacy code.
Presented at PHP Benelux '10
The document discusses testing legacy Rails applications. It provides steps to get testing set up on a legacy Rails app, including creating a test database, running migrations, and getting Rake tasks to run tests. It emphasizes starting with one test at a time, finding and fixing bugs, and refactoring code. Examples are given of writing a model test based on application logs and fixing a failure by updating code. The document stresses treating methods as isolated boxes and only testing one thing at a time to incrementally add tests to a legacy codebase.
The document discusses mutation testing, a technique to evaluate test quality by automatically introducing faults ("mutants") into code and checking if tests can detect the faults. It introduces key concepts like mutants, mutation operators, and tools like PIT that make mutation testing practical. While previously limited by performance, modern tools like PIT can analyze large codebases in reasonable time. Mutation testing tests tests more rigorously than code coverage alone by checking tests can detect small code changes.
Google C++ Testing Framework in Visual Studio 2008Andrea Francia
The document summarizes how to set up and use the Google C++ Testing Framework (Google Test) for unit testing C++ code in Visual Studio 2008. It discusses why Google Test was selected over other testing frameworks, provides an overview of its features and how to set it up in a Visual Studio project. It also demonstrates defining tests with the TEST and ASSERT macros and different types of assertions and expectations that can be used within tests.
This document provides an introduction to unit testing in Python and the Pytest framework. It discusses writing unit test code using the unittest framework and Pytest, how to test functions and handle failures. It also covers features of Pytest like skipping and expected failures, fixture setup/teardown, and distributed testing using the xdist plugin.
MUTANTS KILLER - PIT: state of the art of mutation testing system Tarin Gamberini
The document discusses mutation testing and the PIT mutation testing system. It begins with an overview of mutation testing, which involves making small changes to a program to generate mutant versions and running tests against these mutants to evaluate test effectiveness. The document then covers key concepts of PIT including the various mutators it uses to generate mutants and how it leverages test coverage to efficiently run tests against mutants. An example using a sample Ticket class demonstrates how PIT reports can identify weaknesses in tests by showing mutants that were killed or lived. The document promotes using mutation testing and PIT to evaluate test quality and improve test effectiveness at finding faults.
The presentation describes the properties of a good unit test. The code examples are written in java, but should make sense in each object oriented programming language.
If someone tells you that it is impossible to reimplement some piece of software to be compatible with a newer technology, that is most often not truth.
This is the story about porting RestrictedPython, one of the core packages of Zope to be compatible with Python 3.
This document provides an overview of GoogleMock, a mocking framework for C++. It defines what a mock object is and why they are useful for testing. GoogleMock allows specifying expectations for mock method calls, including how many times a method will be called and what it will return. It provides matchers to check arguments and actions to define return values or behaviors. The document demonstrates how to write mock classes, set expectations, and use mocks in tests to verify code interactions and behavior.
Given that the database, as the canonical repository of data, is the most important part of many applications, why is it that we don't write database unit tests? This talk promotes the practice of implementing tests to directly test the schema, storage, and functionality of databases.
The document discusses automated testing in Python and other languages. It covers unit testing, how unit tests work in Python using the unittest module, the benefits of testing like refactoring with confidence and faster debugging. It also briefly mentions test frameworks for other languages like Java, Perl, PHP and Erlang. The key themes are that testing finds bugs, helps refactor code safely, and that when frameworks have shortcomings the better approach is to help fix them rather than starting new ones.
This document provides an overview of the Python unittest module for writing and running automated tests. It discusses how the unittest.TestCase class is used to define test classes with methods named "test_" that contain assertions. The unittest module then handles running the tests and provides features like test organization, discovery of test methods, and integration with other tools.
Test driven development and unit testing with examples in C++Hong Le Van
Test-driven development (TDD) relies on short development cycles of writing a failing test case, producing code to pass that test, and refactoring the code. Unit testing tests individual units of code by isolating each part and showing they work correctly. Boost.Test is a popular C++ unit testing framework that allows organizing tests into suites and fixtures, and provides assertions and output of results. A minimal Boost.Test example defines a test case using BOOST_AUTO_TEST_CASE that contains an assertion like BOOST_CHECK_EQUAL to test that 2+2 equals 4.
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system Tarin Gamberini
The document discusses mutation testing and the PIT mutation testing system. It begins by explaining the concepts of mutation testing, how PIT works, and the different mutators that PIT uses to generate mutants. It then provides examples of using PIT on a sample Ticket class to generate mutants and how the test results can help improve test coverage and discover weak tests.
Links from the talk are available at:
https://github.com/claremacrae/talks/blob/master/Quickly_Testing_Qt_Desktop_Applications.md#top
Presented at Meeting C++ in Berlin on 15 November 2019.
Abstract: You've inherited some Qt GUI code: it's valuable, but it doesn't have tests, and it wasn't designed to be testable, so you need to start refactoring. But you can't refactor safely until the code has tests, and you can't add tests without refactoring! How can you ever break out of this loop?
Clare will review the challenges and potential sources of error that are specific to code that uses the Qt cross-platform graphical user interface library, and then describe how to guard against them.
There are many options for unit-testing Qt code, including Qt Test, Google Test and Catch. As well as covering those, and general principles for applying them, Clare will present a small but surprisingly effective C++11 library for applying "Approval Tests" to cross-platform Qt code.
Finally, she will briefly cover some other tools that can aid with inspecting and maintaining Qt code, which can in turn improve testability. Attendees will discover some quick, practical techniques to help write unit tests and integration tests for Qt code.
This document provides an introduction to Test Driven Development (TDD) in Italian. It defines key TDD concepts like "test first" and automating tests. It then provides examples of using TDD to develop a parser for the "df" command output and features for an astrology horoscope application. The examples demonstrate the TDD process of writing a failing test, then code to pass the test, and refactoring. Rules for TDD like keeping tests passing and writing tests for all features are also outlined.
This document discusses unit testing in Python. It explains that unit tests should be written before code to automatically test inputs and outputs. The code is then written to pass the tests. Tests are implemented by creating test classes that inherit from unittest.TestCase and adding test methods with assert statements. The document provides an example test and steps for creating unit tests, including importing unittest and the code to test.
The document discusses test driven development (TDD) and how it can be used with Visual Studio 2010. It defines TDD as a process where developers write a failing test first, then code to pass the test, and refactor the code. The document outlines benefits of TDD like reduced bugs and defects, increased code flexibility, and easier addition of new features. It provides some advice on writing tests and using tools in Visual Studio 2010 like code coverage and contracts to help focus on TDD. Demo code is shown using unit testing and web testing in Visual Studio 2010.
Join core JUnit 5 committer Sam Brannen to gain insight on the latest new features in JUnit 5 as well as what’s on the horizon.
In this presentation we will look at exciting new features that have been added in JUnit 5 over the past year, including temporary directories, custom display name generators, method ordering, timeouts, the Test Kit, and powerful new extension APIs. If you haven't yet made the switch from JUnit 4 to JUnit 5 you will definitely want to check out this presentation.
In closing, Sam will also provide a few tips on how to use JUnit Jupiter to test Spring and Spring Boot apps.
In this talk we are going tο… talk about what unit testing is, how you can apply it to ensure your code works as expected and how TDD can help you write new and refactor existing code. Also about how to decide what to test and how you can test real world iOS apps. Finally, we will go through a few tips and tricks that made unit testing in Swift and Xcode 'click' for me and can hopefully help you too.
This document provides an introduction to object-oriented programming concepts in Java including classes, objects, encapsulation, inheritance, and polymorphism. It begins with an overview of Java 102 course details and introduces fundamental OOP concepts like classes, objects, and encapsulation. It provides examples to illustrate these concepts and explains how to create objects from classes. The document then covers other OOP pillars like inheritance, polymorphism, method overloading and overriding. It includes hands-on exercises for readers to practice creating classes, objects, inheritance and method overloading.
The document introduces C++ templates and exceptions. It discusses three approaches to functions that implement identical tasks for different data types: the naïve approach with unique function names, function overloading with the same name, and function templates where the compiler generates individual functions. It also covers class templates where the compiler generates distinct class types, and how to instantiate class and function templates by substituting the template argument. Finally, it discusses exception handling in C++ using try, throw, catch blocks to handle errors and exceptions thrown during program execution.
Google C++ Testing Framework in Visual Studio 2008Andrea Francia
The document summarizes how to set up and use the Google C++ Testing Framework (Google Test) for unit testing C++ code in Visual Studio 2008. It discusses why Google Test was selected over other testing frameworks, provides an overview of its features and how to set it up in a Visual Studio project. It also demonstrates defining tests with the TEST and ASSERT macros and different types of assertions and expectations that can be used within tests.
This document provides an introduction to unit testing in Python and the Pytest framework. It discusses writing unit test code using the unittest framework and Pytest, how to test functions and handle failures. It also covers features of Pytest like skipping and expected failures, fixture setup/teardown, and distributed testing using the xdist plugin.
MUTANTS KILLER - PIT: state of the art of mutation testing system Tarin Gamberini
The document discusses mutation testing and the PIT mutation testing system. It begins with an overview of mutation testing, which involves making small changes to a program to generate mutant versions and running tests against these mutants to evaluate test effectiveness. The document then covers key concepts of PIT including the various mutators it uses to generate mutants and how it leverages test coverage to efficiently run tests against mutants. An example using a sample Ticket class demonstrates how PIT reports can identify weaknesses in tests by showing mutants that were killed or lived. The document promotes using mutation testing and PIT to evaluate test quality and improve test effectiveness at finding faults.
The presentation describes the properties of a good unit test. The code examples are written in java, but should make sense in each object oriented programming language.
If someone tells you that it is impossible to reimplement some piece of software to be compatible with a newer technology, that is most often not truth.
This is the story about porting RestrictedPython, one of the core packages of Zope to be compatible with Python 3.
This document provides an overview of GoogleMock, a mocking framework for C++. It defines what a mock object is and why they are useful for testing. GoogleMock allows specifying expectations for mock method calls, including how many times a method will be called and what it will return. It provides matchers to check arguments and actions to define return values or behaviors. The document demonstrates how to write mock classes, set expectations, and use mocks in tests to verify code interactions and behavior.
Given that the database, as the canonical repository of data, is the most important part of many applications, why is it that we don't write database unit tests? This talk promotes the practice of implementing tests to directly test the schema, storage, and functionality of databases.
The document discusses automated testing in Python and other languages. It covers unit testing, how unit tests work in Python using the unittest module, the benefits of testing like refactoring with confidence and faster debugging. It also briefly mentions test frameworks for other languages like Java, Perl, PHP and Erlang. The key themes are that testing finds bugs, helps refactor code safely, and that when frameworks have shortcomings the better approach is to help fix them rather than starting new ones.
This document provides an overview of the Python unittest module for writing and running automated tests. It discusses how the unittest.TestCase class is used to define test classes with methods named "test_" that contain assertions. The unittest module then handles running the tests and provides features like test organization, discovery of test methods, and integration with other tools.
Test driven development and unit testing with examples in C++Hong Le Van
Test-driven development (TDD) relies on short development cycles of writing a failing test case, producing code to pass that test, and refactoring the code. Unit testing tests individual units of code by isolating each part and showing they work correctly. Boost.Test is a popular C++ unit testing framework that allows organizing tests into suites and fixtures, and provides assertions and output of results. A minimal Boost.Test example defines a test case using BOOST_AUTO_TEST_CASE that contains an assertion like BOOST_CHECK_EQUAL to test that 2+2 equals 4.
MUTANTS KILLER (Revised) - PIT: state of the art of mutation testing system Tarin Gamberini
The document discusses mutation testing and the PIT mutation testing system. It begins by explaining the concepts of mutation testing, how PIT works, and the different mutators that PIT uses to generate mutants. It then provides examples of using PIT on a sample Ticket class to generate mutants and how the test results can help improve test coverage and discover weak tests.
Links from the talk are available at:
https://github.com/claremacrae/talks/blob/master/Quickly_Testing_Qt_Desktop_Applications.md#top
Presented at Meeting C++ in Berlin on 15 November 2019.
Abstract: You've inherited some Qt GUI code: it's valuable, but it doesn't have tests, and it wasn't designed to be testable, so you need to start refactoring. But you can't refactor safely until the code has tests, and you can't add tests without refactoring! How can you ever break out of this loop?
Clare will review the challenges and potential sources of error that are specific to code that uses the Qt cross-platform graphical user interface library, and then describe how to guard against them.
There are many options for unit-testing Qt code, including Qt Test, Google Test and Catch. As well as covering those, and general principles for applying them, Clare will present a small but surprisingly effective C++11 library for applying "Approval Tests" to cross-platform Qt code.
Finally, she will briefly cover some other tools that can aid with inspecting and maintaining Qt code, which can in turn improve testability. Attendees will discover some quick, practical techniques to help write unit tests and integration tests for Qt code.
This document provides an introduction to Test Driven Development (TDD) in Italian. It defines key TDD concepts like "test first" and automating tests. It then provides examples of using TDD to develop a parser for the "df" command output and features for an astrology horoscope application. The examples demonstrate the TDD process of writing a failing test, then code to pass the test, and refactoring. Rules for TDD like keeping tests passing and writing tests for all features are also outlined.
This document discusses unit testing in Python. It explains that unit tests should be written before code to automatically test inputs and outputs. The code is then written to pass the tests. Tests are implemented by creating test classes that inherit from unittest.TestCase and adding test methods with assert statements. The document provides an example test and steps for creating unit tests, including importing unittest and the code to test.
The document discusses test driven development (TDD) and how it can be used with Visual Studio 2010. It defines TDD as a process where developers write a failing test first, then code to pass the test, and refactor the code. The document outlines benefits of TDD like reduced bugs and defects, increased code flexibility, and easier addition of new features. It provides some advice on writing tests and using tools in Visual Studio 2010 like code coverage and contracts to help focus on TDD. Demo code is shown using unit testing and web testing in Visual Studio 2010.
Join core JUnit 5 committer Sam Brannen to gain insight on the latest new features in JUnit 5 as well as what’s on the horizon.
In this presentation we will look at exciting new features that have been added in JUnit 5 over the past year, including temporary directories, custom display name generators, method ordering, timeouts, the Test Kit, and powerful new extension APIs. If you haven't yet made the switch from JUnit 4 to JUnit 5 you will definitely want to check out this presentation.
In closing, Sam will also provide a few tips on how to use JUnit Jupiter to test Spring and Spring Boot apps.
In this talk we are going tο… talk about what unit testing is, how you can apply it to ensure your code works as expected and how TDD can help you write new and refactor existing code. Also about how to decide what to test and how you can test real world iOS apps. Finally, we will go through a few tips and tricks that made unit testing in Swift and Xcode 'click' for me and can hopefully help you too.
This document provides an introduction to object-oriented programming concepts in Java including classes, objects, encapsulation, inheritance, and polymorphism. It begins with an overview of Java 102 course details and introduces fundamental OOP concepts like classes, objects, and encapsulation. It provides examples to illustrate these concepts and explains how to create objects from classes. The document then covers other OOP pillars like inheritance, polymorphism, method overloading and overriding. It includes hands-on exercises for readers to practice creating classes, objects, inheritance and method overloading.
The document introduces C++ templates and exceptions. It discusses three approaches to functions that implement identical tasks for different data types: the naïve approach with unique function names, function overloading with the same name, and function templates where the compiler generates individual functions. It also covers class templates where the compiler generates distinct class types, and how to instantiate class and function templates by substituting the template argument. Finally, it discusses exception handling in C++ using try, throw, catch blocks to handle errors and exceptions thrown during program execution.
1. The document introduces C++ templates and exceptions. It discusses function templates, class templates, and how they allow generating functions and classes for different data types.
2. It also covers exception handling in C++ using try, throw, and catch. Exceptions represent errors that require special processing. The try block encloses code that may throw exceptions, and catch blocks provide exception handlers.
3. Rethrowing exceptions allows an exception handler to pass the exception to the next enclosing try block if it cannot handle the exception itself. Exception specifications and uncaught exceptions are also discussed.
C++ templates and exceptions allow for more robust and reusable code. Templates allow functions and classes to work with different data types by using placeholder types that are substituted at compile-time. This avoids duplicating code and reduces errors. Exceptions provide a mechanism to handle errors and unexpected events in code through throwing and catching exception objects. Exceptions allow code to exit a block and transfer control to dedicated error handling code. Together, templates and exceptions make C++ code more flexible, reusable and fault-tolerant.
Unit testing, everyone talks about it and wants to do it but never gets around to actually start testing. Complex spaghetti code and time / budget pressures are often the reasons why nobody dives in and gets started with testing. But when the application breaks, and people loose money or worse it's often too late.
In this talk I will take you on a journey with real examples that will show you how you can set up your tests, how to test complex situations with legacy spaghetti code, test web services, database interactions and how to gradually build a solid foundation to safeguard the core code base and everything around it.
Don't you want to be confident when you walk out the office?
Slides for a college course at City College San Francisco. Based on "The Shellcoder's Handbook: Discovering and Exploiting Security Holes ", by Chris Anley, John Heasman, Felix Lindner, Gerardo Richarte; ASIN: B004P5O38Q.
Instructor: Sam Bowne
Class website: https://samsclass.info/127/127_F18.shtml
Dart is a productive way to develop future JavaScript apps today. It comes with a complete set of development tools and will help ease development of EcmaScript 6 in 2016. Dart simplifies development by allowing optional variable types and single inheritance for classes. It supports concurrency without threads. Popular IDEs like IntelliJ, WebStorm, and Eclipse support Dart development. Code can run in the Dart VM for fast feedback or compile to JavaScript to run in browsers.
The document discusses various topics in Objective-C including variables, data types, categories, protocols, and composite objects. It provides code examples to illustrate initializing objects, variable scope, enumerated data types, typedefs, data type conversion, categories, class extensions, protocols, delegates, and composite objects in Objective-C and compares some of these concepts to Java.
Automated integration tests for ajax applications (с. карпушин, auriga)Mobile Developer Day
The document discusses automated integration tests for AJAX applications. It covers motivations like reliability and reducing bug time. Challenges include asynchronous behavior and lack of tools. Solutions presented are Selenium and jWebUnit for testing, as well as configuring continuous integration. Experience shows a project spending less time on manual testing after implementing automated tests.
Turku loves-storybook-styleguidist-styled-componentsJames Stone
The document discusses different tools for building design systems in React, including Storybook, Styleguidist, and Styled Components. It explains that Storybook is focused on component development and testing ("the workshop"), while Styleguidist generates documentation and is meant to share the design system externally ("the storefront"). Styled Components is presented as a good option for managing CSS in React projects. Examples are provided for each tool to illustrate how they can be used.
Concurrent Collections Object In Dot Net 4Neeraj Kaushik
The document discusses various concurrent collections introduced in .NET 4.0 that provide thread safety. These include ConcurrentQueue, ConcurrentDictionary, ConcurrentBag, and BlockingCollection. ConcurrentQueue provides a thread-safe first-in first-out collection. ConcurrentDictionary provides a thread-safe collection of key-value pairs. ConcurrentBag provides an unordered thread-safe collection. BlockingCollection adds blocking and bounding capabilities to thread-safe collections.
This document describes stacks and queues data structures and their application programming interfaces (APIs). It defines the common operations for stacks and queues, including push, pop, enqueue, and dequeue. It provides examples of using stacks and queues to evaluate postfix expressions and read input from a queue. Stacks and queues are widely used in applications like browsers, interpreters, and printing. The document also covers generics, autoboxing/unboxing, and real-world examples of stacks in programming languages and PostScript.
Adding a modern twist to legacy web applicationsJeff Durta
Avoid misery of working with legacy code
We will see how you can add independent and isolated components to existing pages; pages that may be difficult to change
React and Flux allow you to make self-contained additions that handle their own data access/persistence
Breaking Dependencies to Allow Unit TestingSteven Smith
Unit testing software can be difficult, especially when the software wasn't designed to be testable. Dependencies on infrastructure concerns and software we don't control are one of the biggest contributors to testing difficulty. In this session, you'll learn the difference between unit tests and other kinds of tests, how to recognize and invert dependencies, and how to unit test your code's interactions with these dependencies without testing the infrastructure itself.
Presented at FalafelCON 2014, San Francisco, September 2014
Breaking Dependencies To Allow Unit Testing - Steve Smith | FalafelCON 2014FalafelSoftware
Unit testing software can be difficult, especially when the software wasn't designed to be testable. Dependencies on infrastructure concerns and software we don't control are one of the biggest contributors to testing difficulty. In this session, you'll learn the difference between unit tests and other kinds of tests, how to recognize and invert dependencies, and how to unit test your code's interactions with these dependencies without testing the infrastructure itself.
This document discusses code metrics and refactoring. It begins with an introduction to metrics and how they can be used to evaluate code quality by measuring attributes like complexity, coupling, and cohesion. Several specific metrics are discussed like CBO, CC, and LCOM. The document then discusses refactoring and how metrics can help identify areas of code that need improvement. Refactoring is presented as an important process to prevent software decay and allow code to be improved over time through iterative testing and modification.
TDD with Puppet Tutorial presented at Cascadia IT Conference 2014-03-07garrett honeycutt
Test Driven Development (TDD) with Puppet Tutorial that was given at Cascadia IT Conference in Seattle on 2014-03-07 by Garrett Honeycutt of LearnPuppet.com.
Follow me at @learnpuppet
The document discusses tools and techniques for making Java development more enjoyable. It recommends using libraries like Mockito, Guice and Guava to simplify testing and dependency injection. It also suggests using builder patterns, writing concise yet descriptive unit tests, and avoiding string-typing in favor of object-oriented types.
Understanding of Self - Applied Social Psychology - Psychology SuperNotesPsychoTech Services
A proprietary approach developed by bringing together the best of learning theories from Psychology, design principles from the world of visualization, and pedagogical methods from over a decade of training experience, that enables you to: Learn better, faster!
Covey says most people look for quick fixes. They see a big success and want to know how he did it, believing (and hoping) they can do the same following a quick bullet list.
But real change, the author says, comes not from the outside in, but from the inside out. And the most fundamental way of changing yourself is through a paradigm shift.
That paradigm shift is a new way of looking at the world. The 7 Habits of Highly Effective People presents an approach to effectiveness based on character and principles.
The first three habits indeed deal with yourself because it all starts with you. The first three habits move you from dependence from the world to the independence of making your own world.
Habits 4, 5 and 6 are about people and relationships. The will move you from independence to interdependence. Such, cooperating to achieve more than you could have by yourself.
The last habit, habit number 7, focuses on continuous growth and improvement.
You may be stressed about revealing your cancer diagnosis to your child or children.
Children love stories and these often provide parents with a means of broaching tricky subjects and so the ‘The Secret Warrior’ book was especially written for CANSA TLC, by creative writer and social worker, Sally Ann Carter.
Find out more:
https://cansa.org.za/resources-to-help-share-a-parent-or-loved-ones-cancer-diagnosis-with-a-child/
Aggression - Applied Social Psychology - Psychology SuperNotesPsychoTech Services
A proprietary approach developed by bringing together the best of learning theories from Psychology, design principles from the world of visualization, and pedagogical methods from over a decade of training experience, that enables you to: Learn better, faster!
ProSocial Behaviour - Applied Social Psychology - Psychology SuperNotesPsychoTech Services
A proprietary approach developed by bringing together the best of learning theories from Psychology, design principles from the world of visualization, and pedagogical methods from over a decade of training experience, that enables you to: Learn better, faster!
2. Background
• Experience: 10+ years as a developer of various systems
• Projects from the scratch: 8 (2 very large)
• Projects with legacy code: 6 (4 very large)
• Projects with good tests: 4 (1 with legacy code)
• Frameworks: xUnit, MsTests, NUnit
3. Rule 1: Use Bottom-Up (Inside-Out)
• For new systems → Top-Down (Outside-In)
• For systems with legacy code → Bottom-Up (Inside-Out)
• Reasons
• Cannot be properly designed upfront
• Cannot modify components
• Cannot grasp all components
• Cannot mock/stub legacy components
• Interactions have side effects
• Change as little as possible
• Balance
• When injecting the change → bottom-up
• When implementing the change → top-down
4. Rule 1: Example (way of thinking)
public class EuropeShop : Shop
{
public override void CreateSale()
{
var items = LoadSelectedItemsFromDb();
var taxes = new EuropeTaxes();
var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList();
var cart = new Cart();
cart.Add(saleItems);
taxes.ApplyTaxes(cart);
SaveToDb(cart);
}
}
// TODO > NEW FEATURE > Send notification to accounting if cart total amount exceeds 1000
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
5. Rule 2: Test Modified Code ONLY
• Cannot grasp all use cases
• Writing tests for all use cases requires enormous time
• Legacy Code was accepted → works as expected
• Your modification is the only thing which breaks the
stable system
• Don’t bother about Code Coverage
6. Rule 2: Example (new feature)
public class EuropeShop : Shop
{
public override void CreateSale()
{
var items = LoadSelectedItemsFromDb();
var taxes = new EuropeTaxes();
var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList();
var cart = new Cart();
cart.Add(saleItems);
taxes.ApplyTaxes(cart);
// TODO
SaveToDb(cart);
}
}
public class EuropeShop : Shop
{
public override void CreateSale()
{
var items = LoadSelectedItemsFromDb();
var taxes = new EuropeTaxes();
var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList();
var cart = new Cart();
cart.Add(saleItems);
taxes.ApplyTaxes(cart);
new EuropeShopNotifier().Send(cart); // NEW FEATURE
SaveToDb(cart);
}
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
7. Rule 3: Test Requirements ONLY
• Users = classes which use your code
• Consider use cases of method, class, component
• Consider behaviour of the code
• BDD, Feature testing
• Extract responsibilities
8. Rule 3: Example (responsibilities)
public class EuropeShop : Shop
{
public override void CreateSale()
{
// 1) load from DB
var items = LoadSelectedItemsFromDb();
// 2) Tax-object creates SaleItem and
// 4) goes through items and apply taxes
var taxes = new EuropeTaxes();
var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList();
// 3) creates a cart and 4) applies taxes
var cart = new Cart();
cart.Add(saleItems);
taxes.ApplyTaxes(cart);
new EuropeShopNotifier().Send(cart);
// 4) store to DB
SaveToDb(cart);
}
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
public class EuropeShop : Shop
{
public override void CreateSale()
{
// 1) extracted to a repository
var itemsRepository = new ItemsRepository();
var items = itemsRepository.LoadSelectedItems();
// 2) extracted to a mapper
var saleItems = items.ConvertToSaleItems();
// 3) still creates a cart
var cart = new Cart();
cart.Add(saleItems);
// 4) all routines to apply taxes are extracted to the Tax-object
new EuropeTaxes().ApplyTaxes(cart);
new EuropeShopNotifier().Send(cart);
// 5) extracted to a repository
itemsRepository.Save(cart);
}
}
9. Rule 3: Example (tests)
public class EuropeTaxesTests
{
public void Should_not_fail_for_null()
{
}
public void Should_apply_taxes_to_items()
{
}
public void Should_apply_taxes_to_whole_cart()
{
}
public void Should_apply_taxes_to_whole_cart_and_change_items()
{
}
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
public class EuropeShopNotifierTests
{
public void Should_not_send_when_less_or_equals_to_1000()
{
// arrange
var cart = new Cart();
var notifier = new EuropeShopNotifier();
// add items to cart
// act
notifier.Send(cart);
// assert
// PROBLEM: how to verify if we don't have access to the object?
}
public void Should_send_when_greater_than_1000()
{
}
public void Should_raise_exception_when_cannot_send()
{
}
}
10. Rule 4: Inject Tested Code ONLY
• Don’t change legacy code
• Use technique Sprout method/class
• New testable code is called from the old not-testable
• Old code is not changed
• Use technique Wrap method
• New code goes before/after the old not-testable one
• Create a new method to call the new and old one
11. Rule 4: Example (Sprout method)
public class EuropeShop : Shop
{
public override void CreateSale()
{
var items = LoadSelectedItemsFromDb();
var taxes = new EuropeTaxes();
var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList();
var cart = new Cart();
cart.Add(saleItems);
taxes.ApplyTaxes(cart);
// TODO
SaveToDb(cart);
}
}
public class EuropeShop : Shop
{
public override void CreateSale()
{
var items = LoadSelectedItemsFromDb();
var taxes = new EuropeTaxes();
var saleItems = items.Select(item => taxes.ApplyTaxes(item)).ToList();
var cart = new Cart();
cart.Add(saleItems);
taxes.ApplyTaxes(cart);
new EuropeShopNotifier().Send(cart); // Sprout method
SaveToDb(cart);
}
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
12. Rule 4: Example (Wrap method)
public class EuropeTaxes : Taxes
{
internal override SaleItem ApplyTaxes(Item item)
{
var saleItem = new SaleItem(item)
{
SalePrice = item.Price*1.2m
};
return saleItem;
}
internal override void ApplyTaxes(Cart cart)
{
if (cart.TotalSalePrice <= 300m) return;
var exclusion = 30m/cart.SaleItems.Count;
foreach (var item in cart.SaleItems)
if (item.SalePrice - exclusion > 100m)
item.SalePrice -= exclusion;
}
}
public class EuropeTaxes : Taxes
{
internal override void ApplyTaxes(Cart cart)
{
ApplyToItems(cart);
ApplyToCart(cart);
}
private void ApplyToItems(Cart cart)
{
foreach (var item in cart.SaleItems)
item.SalePrice = item.Price*1.2m;
}
private void ApplyToCart(Cart cart)
{
if (cart.TotalSalePrice <= 300m) return;
var exclusion = 30m / cart.SaleItems.Count;
foreach (var item in cart.SaleItems)
if (item.SalePrice - exclusion > 100m)
item.SalePrice -= exclusion;
}
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
13. Rule 5: Break Hidden Dependencies
• Stop instantiate classes in methods
• Extract initialization to constructor
• Replace usages of class with usages of interface/abstract
• Low coupling, High cohesion
• Extract giant methods to classes
• Remove violations of Law of Demeter
“Cohesion partitions your functionality so that it is concise and closest to
the data relevant to it, whilst decoupling ensures that the functional
implementation is isolated from the rest of the system.”
- Adrian Regan @ stackoverflow.com
14. Rule 5: Example (dependencies)
public class EuropeShop : Shop
{
public override void CreateSale()
{
var itemsRepository = new ItemsRepository();
var items = itemsRepository.LoadSelectedItems();
var saleItems = items.ConvertToSaleItems();
var cart = new Cart();
cart.Add(saleItems);
new EuropeTaxes().ApplyTaxes(cart);
new EuropeShopNotifier().Send(cart);
itemsRepository.Save(cart);
}
}
public class EuropeShop : Shop
{
private readonly IItemsRepository _itemsRepository;
private readonly Taxes.Taxes _europeTaxes;
private readonly INotifier _europeShopNotifier;
public override void CreateSale()
{
var items = _itemsRepository.LoadSelectedItems();
var saleItems = items.ConvertToSaleItems();
var cart = new Cart();
cart.Add(saleItems);
_europeTaxes.ApplyTaxes(cart);
_europeShopNotifier.Send(cart);
_itemsRepository.Save(cart);
}
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
Skipped by now, but we can use Factory to isolate
15. Rule 6: The Less “Big” tests, the Better
• “Big” tests
• Integration tests
• End-to-end tests
• UI tests
• Complexity grows by exponent
• Double time to maintain and write
• Special cases:
• Performance tests
• Load tests
• DON’T substitute unit tests with integration tests
16. Rule 7: Don’t Test Private Methods
• Responsibility violation sign
• Fragile tests
• Not WHAT class does, but HOW it does
• Don’t convert private methods to public ones
• Extract and use internal for module inside logic
• Consider new classes for private methods
• Consider internal classes as complete tools
17. Rule 7: Example (test)
public class EuropeTaxes : Taxes {
public override void ApplyTaxes(Cart cart) {
ApplyToItems(cart);
ApplyToCart(cart);
}
private void ApplyToItems(Cart cart) {
foreach (var item in cart.SaleItems)
item.SalePrice = item.Price*1.2m;
}
private void ApplyToCart(Cart cart) {
if (cart.TotalSalePrice <= 300m) return;
var exclusion = 30m / cart.SaleItems.Count;
foreach (var item in cart.SaleItems)
if (item.SalePrice - exclusion > 100m)
item.SalePrice -= exclusion;
}
}
public class EuropeTaxesTests {
public void Should_not_fail_for_null() {
}
public void Should_apply_taxes_to_items() {
}
public void Should_apply_taxes_to_whole_cart() {
}
public void Should_apply_taxes_to_whole_cart_and_change_items() {
}
public void Should_apply_taxes_to_cart_greater_300() {
}
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
18. Rule 7: Example (test body)
public void Should_apply_taxes_to_cart_greater_300()
{
// arrange
// list of items which will create a cart greater 300
var saleItems = new List<Item>(new []{new Item {Price = 83.34m},
new Item {Price = 83.34m},new Item {Price = 83.34m}})
.ConvertToSaleItems();
var cart = new Cart();
cart.Add(saleItems);
const decimal expected = 83.34m*3*1.2m;
// act
new EuropeTaxes().ApplyTaxes(cart);
// assert
Assert.Equal(expected, cart.TotalSalePrice);
}
Source code: https://github.com/xtrmstep/ApplyingTddToLegacyCode
19. Rule 8: Don’t Test Algorithms
• Fragile tests
• Don’t care about number of calls
• Don’t care about which method is executed
• Do care about effects
20. Rule 9: Stop Modifying Legacy Code w/o Tests
• Add tests to Definition of Done & Code Review
• May look as a waste of time at the early stage
• Cumulative result at the later stage
• Always practicing
21. See Also
• Book “Working Effectively with Legacy Code” by Michael Feathers
• https://danlimerick.wordpress.com/2012/04/25/tdd-when-up-to-your-neck-in-legacy-code/
• https://danlimerick.wordpress.com/2012/06/11/breaking-hidden-dependencies/
• https://danlimerick.wordpress.com/2012/04/25/the-legacy-code-lifecycle/
• https://www.quora.com/Should-you-unit-test-private-methods-on-a-class
• http://blog.ploeh.dk/2015/09/22/unit-testing-internals/
• https://medium.com/javascript-scene/5-common-misconceptions-about-tdd-unit-tests-863d5beb3ce9#.uav3gih3k
• http://www.daedtech.com/intro-to-unit-testing-5-invading-legacy-code-in-the-name-of-testability/
• https://en.wikipedia.org/wiki/Law_of_Demeter