Refactoring & Testability

24
Refactoring & Testability

description

Refactoring & Testability. Testing in OOP programming. No life in flexible methodologies and for refactoring-infected developers without SOME kind of AUTOMATED tests Tests are not a panacea, don't be categorical and skeptic. Tremendous use when possible to write - PowerPoint PPT Presentation

Transcript of Refactoring & Testability

Page 1: Refactoring & Testability

Refactoring & Testability

Page 2: Refactoring & Testability

Testing in OOP programming

No life in flexible methodologies and for refactoring-infected developers without SOME kind of AUTOMATED tests

Tests are not a panacea, don't be categorical and skeptic. Tremendous use when possible to write

JUnit is a tool, so "не забивайте гвозди штангенциркулем"

Unit testing forces as to refactor!!!

Page 3: Refactoring & Testability

Unit testing benefits (1 of 2)

Can be applied to incomplete application

JUnit is the first User of your code!

Kinds of tests Unit->Integration->Function->Stress

Characteristic is the amount of application build already

Makes me confident that I prevent my peer developers and QAs from finding tedious errors in my code.

Less code to debug under test (as opposed to functional tests)

Page 4: Refactoring & Testability

Unit testing benefits (2 of 2)

Can simulate errors

Test not only successful path (as integration test basically does), but the scenario when something can fail!

Testing exceptions

Can act as a perfect and up-to-date documentation

Encourage us for refactoring! Probably the most important advantage.

Page 5: Refactoring & Testability

Example. Testing exceptions:

try {

methodWhichThrowsException();

fail(“Description”);

} catch(ApplicationException meaningfulNameExpected) {

assertNotNull(“Explanation why expected”,expected)

}

Page 6: Refactoring & Testability

Mocking

Programming on interfaces vs. concrete classes

Subclassing from concrete classes is a testing smell

If I subclass and override a method, what do I actually test?

MockObjects.com (JMock)

No! business logic. The mock should 100% comply to contract under CURRENT test. JMock is well suited for this rule.

Page 7: Refactoring & Testability

Example:

Testing e-mail service.

Page 8: Refactoring & Testability

When to use mocks

Notes on page 4

Page 9: Refactoring & Testability

Too many mocks? Hard to setup a test?

Mock lower OR refactor!

If a big framework has single but very smart method doWork() it's most likely a bad idea to test it

Test may be skipped if the method's contract is based solely on other contracts

Page 10: Refactoring & Testability

Example:

Shopping cart test (com.luxoft.tests.exercises.shoppingcart)

Page 11: Refactoring & Testability

Refactoring

Hardness to write (set up) unit tests FORCES us to simplify (factorize) the method or class or module.

Bad code is impossible to well unit test!

there is one-to-one dependency between good code and ability to write good tests

Code smells (detect manually or by means of PMD, etc.) Writing tests

Page 12: Refactoring & Testability

Refactoring DON’Ts (1 of 3)

Make Your Own Dependencies

Heavy Duty Constructors

Depend on Concrete Classes

Conditional Slalom. if-branches and switch statements

Depend on Large Context Objects

Use Statics

Use Global Flags

Page 13: Refactoring & Testability

Refactoring DON’Ts (2 of 3)

Use Singletons Everywhere

Use Primitives Wherever Possible

Look for Everything You Need (Law of Demeter)

Couple functional code directly to the external systems it depends on

Mix Object Lifecycles

Side Effects

Page 14: Refactoring & Testability

Refactoring DON’Ts (3 of 3)

Create Utility Classes and Functions/Methods

Create Managers and Controllers

Do Complicated Creation Work in Objects

Utils!

Final Methods

Handcuff your users to Specific Types

Use static initializes

Page 15: Refactoring & Testability

Example. Don’t depend on Large Context Objects:

class Mechanic {

Engine engine;

Mechanic(Context context) {

this.engine = context.getEngine();

}

}

Page 16: Refactoring & Testability

Example. Violate the law of Demeter:

class Monitor {

SparkPlug sparkPlug;

Monitor(Context context) {

this.sparkPlug = context.

getCar().getEngine().

getPiston().getSparkPlug();

}

}

Page 17: Refactoring & Testability

Inversion of controls & objects construction

Hollywood principle vs. factory method principle

Collaboration graph and construction graph

Remove new operators from application code as much as possible

Conclusion: separate classes with business logic and factories which create classes

Page 18: Refactoring & Testability

Example. Avoid new op. for testability:

class House {

private final Kitchen kitchen = new Kitchen();

private boolean isLocked;

private boolean isLocked() {

return isLocked;

}

private boolean lock() {

kitchen.lock();

isLocked = true;

}

}

Page 19: Refactoring & Testability

Benefits of IoC

Allows us to mock in tests

Allows us to use single instance of a class (saves us memory)

Shortens the methods and make them more precise (only business logic).

Real isolation.

Page 20: Refactoring & Testability

Inversion of controls. Conclusion

It’s good both for tests and for code’s health to:

separate the business logic from factory code to create required objects (for that business logic)

Doing so is really boring! Let the computer do boring stuff.

Use IoC containers

Dependency injection (wiring) Use empty, param-less constructors. Use setters!

Page 21: Refactoring & Testability

Refactoring for testability. Final thoughts

Consider IoC vs. factory method

Example: Isolate system resources getRemoteDataObtainer()

Test coverage and test quality

100% coverage does not mean that the method is 100% tested. Example.

Test quality measurement tools

Clover Jester/Muclipse

Oil detector in a car’s engine

Page 22: Refactoring & Testability

When Unit tests are good? (1 of 2)

Continuous and automated

Hudson / Email reports

Fast, easy to run

Written early to force Refactoring and detect design errors

No real opportunity to use integration tests

When code is good writing tests is fun. Should be easy

Page 23: Refactoring & Testability

When tests are good? (2 of 2)

When there a lots of tests!!!

We MOCK a contract, i.e. believe that a mocked method follows the contract. Test that!

Test as less code outside of the method under test as possible.

Ideally:

test=(test_method_code) + (private_methods) + (mocks)

Page 24: Refactoring & Testability

Unit tests is a must activity for a developer

Unit tests are not even a way to test code, but for a developer is a very much a way to develop perfect code

Just try!