Upload
others
View
2
Download
0
Embed Size (px)
Citation preview
Test Units Containing Static Dependencies
2010-09-04
Wednesday, September 8, 2010
William Rowden
Co-founded Agile Software company (Gray Hill Solutions, Inc.) in 2001
Wednesday, September 8, 2010
SolutionsIQWednesday, September 8, 2010
SolutionsIQAgile Software Development
Agile Training
Agile Consulting
• Agile Coaching
• Agile Team Services
• Agile Enterprise Rollouts
Wednesday, September 8, 2010
Hobbies
Love to travel
Hablo español(I speak Spanish,我会说西班牙语)
我会说一点儿普通话
Wednesday, September 8, 2010
HistoryBASIC, QBasic, Visual Basic, VBA, Visual Basic.NET, VBScript
Pascal
S+, R
FORTRAN
make, bash
Wednesday, September 8, 2010
LanguagesC++, C# 3.5 (with XAML)
Python
Perl (with HTML)
SQL
Java
Wednesday, September 8, 2010
AgendaWednesday, September 8, 2010
ProblemWednesday, September 8, 2010
ProblemTest a system containing a
hidden dependency on a static method call
Wednesday, September 8, 2010
Code Sample
package com.solutionsiq.wrowden;
public class SystemUnderTest { public ReturnValue methodWithDependecies() { ReturnValue returnValue = Library.staticMethod(); returnValue.doSomething(); return returnValue; }}
Library.staticMethod()
Wednesday, September 8, 2010
Problem
package com.solutionsiq.wrowden;
import static org.junit.Assert.assertEquals;import org.junit.Test;
public class WhenSystemUnderTestHasStaticDependencies {
@Test public void shouldBreakDependency() { final ReturnValue testValue = new ReturnValue(); final SystemUnderTest systemUnderTest = new SystemUnderTest(); assertEquals ("Method gets value from environment.", testValue, systemUnderTest.methodWithDependencies()); }}
Wednesday, September 8, 2010
Problem一个问题...
Wednesday, September 8, 2010
Hidden Dependencies
Internally created objects
Static methods of other classes
Extension methods
Singletons
Static methods of other classes
Wednesday, September 8, 2010
Hidden Dependencies - Potential Problems
early infrastructure choice
set up time
tight coupling
slow tests
Wednesday, September 8, 2010
SolutionsWednesday, September 8, 2010
Design SolutionsWednesday, September 8, 2010
Extract & OverrideWednesday, September 8, 2010
Working Effectively with Legacy
Code
Wednesday, September 8, 2010
EclipseRefactor
Wednesday, September 8, 2010
Extract & Override Call
package com.solutionsiq.wrowden;
public class SystemUnderTest { public ReturnValue methodWithDependencies() { final ReturnValue returnValue = extractedStaticMethod(); returnValue.doSomething(); return returnValue; } protected ReturnValue extractedStaticMethod() { return Library.staticMethod(); }}
Wednesday, September 8, 2010
Eclipse SourceWednesday, September 8, 2010
Extract & Override Callpackage com.solutionsiq.wrowden;
import static org.junit.Assert.assertEquals;import org.junit.Test;
public class WhenSystemUnderTestHasStaticDependencies {
@Test public void shouldBreakDependency() { final ReturnValue testValue = new ReturnValue(); final SystemUnderTest systemUnderTest = new SystemUnderTest() {
@Override protected ReturnValue extractedStaticMethod() { return testValue; } }; final ReturnValue actualValue = systemUnderTest.methodWithDependencies(); assertEquals("Method gets value from environment.", testValue, actualValue); }}
Wednesday, September 8, 2010
Result 结果
Wednesday, September 8, 2010
Extract & Override CallAdvantages:
+ clear
+ fast
+ wide application
Disadvantages:
- hidden bugs
- indirection performance
- multiple methods
- production code policy
好处 坏处
Wednesday, September 8, 2010
VerificationState:
ReturnValue
Behavior:
Library.staticMethod
Wednesday, September 8, 2010
Mock ObjectWednesday, September 8, 2010
ChihuahuaIn Mexico I discussed how to turn a class into an object.
Wednesday, September 8, 2010
Design Patterns:
Elements of Reusable Object-
Oriented Software
Wednesday, September 8, 2010
Interface
“Program to an interface, not an implementation.”
--Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides; Design Patterns: Elements of Reusable Object-Oriented Software
Wednesday, September 8, 2010
Adapter Pattern
“Clients call operations on an Adapter instance. In turn, the adapter calls Adaptee operations that carry out the request.”
Wednesday, September 8, 2010
The Art of Unit Testing
Wednesday, September 8, 2010
Mock Library
Wednesday, September 8, 2010
Interface
package com.solutionsiq.wrowden;
public interface AdaptableLibrary {
ReturnValue staticMethod();
}
Wednesday, September 8, 2010
EasyMock
import static org.easymock.EasyMock.createMock;import static org.easymock.EasyMock.expect;import static org.easymock.EasyMock.replay;import static org.easymock.EasyMock.verify;
Wednesday, September 8, 2010
Test-Driven Development
Fix failing test by calling mock Library
Real system calls Library adapter
Wednesday, September 8, 2010
Dependency Injection
package com.solutionsiq.wrowden;
public class SystemUnderTest { public ReturnValue methodWithDependencies(AdaptableLibrary library) { final ReturnValue returnValue = library.staticMethod(); returnValue.doSomething(); return returnValue; }}
Wednesday, September 8, 2010
Adapter Pattern
package com.solutionsiq.wrowden;
public class LibraryAdapter implements AdaptableLibrary {
@Override public ReturnValue staticMethod() { return Library.staticMethod(); }}
Wednesday, September 8, 2010
Result 结果
Wednesday, September 8, 2010
MockingAdvantages:
+ easy
+ readable
Disadvantages:
- less readable setup
- could require many mocks
- changed static method
好处 坏处
Wednesday, September 8, 2010
Test SolutionsWednesday, September 8, 2010
西安钟楼In China I discussed test
strategies.
Wednesday, September 8, 2010
Test Techniques
if (testableCode = goodCode) {
// try dependency injection
// try mocking
}
testableCode = goodCode
Wednesday, September 8, 2010
Test Techniques
if (goodCode != testableCode) {
// try class loader
// try Aspect-Oriented Programming
}
goodCode = testableCode!
Wednesday, September 8, 2010
Class LoaderWednesday, September 8, 2010
package com.solutionsiq.wrowden;
import static org.junit.Assert.assertEquals;
@RunWith(PowerMockRunner.class)@PrepareForTest(Library.class)public class WhenSystemUnderTestHasStaticDependencies {
@Test public void shouldBreakDependency() { final ReturnValue testValue = new ReturnValue(); final SystemUnderTest systemUnderTest = new SystemUnderTest(); PowerMock.mockStatic(Library.class); EasyMock.expect(Library.staticMethod()).andReturn(testValue); PowerMock.replay(Library.class); assertEquals("Method gets value from environment.", testValue, systemUnderTest.methodWithDependencies()); PowerMock.verify(Library.class); }}
PowerMock
Wednesday, September 8, 2010
Result 结果
Wednesday, September 8, 2010
Class LoadersAdvantages:
+ removes external dependency
+ tests code using a third-party API
Disadvantages:
- doesn’t improve code design
- inhibits useful feedback
好处 坏处
Wednesday, September 8, 2010
Aspect-Oriented Programming
Wednesday, September 8, 2010
Deciding WhichAre there bad smells in the code?
Can you improve the design of the existing code?
How many hidden dependencies are there?
Is performance a problem?
Is the call too simple to break? Or would overriding hide bugs?
Wednesday, September 8, 2010
Questions?
Wednesday, September 8, 2010