SlideShare a Scribd company logo
1 of 51
Extreme Testing at kaChing 
From Commit to Production in 5 minutes 
                   
      Pascal‐Louis Perez –               .com 




               Pascal‐Louis Perez, kaChing Group Inc. 
kaChing: the Investing Talent Marketplace 

• Marketplace for qualified managers 
  – Young professionals 
  – RIAs 
  – Hedge Fund managers 
• Customers can mirror “kaChing Geniuses” 
  – Your own brokerage account 
  – Real time reporting; Analytics; Drift alerts 
• Unparalleled Transparency 
  – See everything: holdings, risk metrics, trades, … 
  – Clear fee structure: management fee. No hidden fees, 
    exit fees, … 
                    Pascal‐Louis Perez, kaChing Group Inc. 
 




    Pascal‐Louis Perez, kaChing Group Inc. 
Our System in 30 Seconds 




       Pascal‐Louis Perez, kaChing Group Inc. 
Testing Matters 

                   Architectural Soundness 
Delighting Customers 




               Pascal‐Louis Perez, kaChing Group Inc. 
Testable Code Because… 
• It allows quick iterations 
• It makes it easier to scale the team 
• It is more cost effective than debugging 
• It obsoletes the need for functional QA 
• It facilitates continuous refactoring, allowing 
  the code to get better with age 
• It attracts the right kind of engineers 

                  Pascal‐Louis Perez, kaChing Group Inc. 
High Level Classification 

     Correctness                   Availability 

λ 

π 



        Pascal‐Louis Perez, kaChing Group Inc. 
High Level Classification 

     Correctness                   Availability 

λ      • Bad: incorrect  but available system 
       • Bad: correct but unavailable system 


π 



        Pascal‐Louis Perez, kaChing Group Inc. 
High Level Classification 

     Correctness                     Availability 
     • Transformations (λ) 
λ    • Interactions (π): send an e‐mail, 
     store data in a db, RPC call 
     • In π implicit global mutable state 

π 



          Pascal‐Louis Perez, kaChing Group Inc. 
High Level Classification 

     Correctness                   Availability 

λ 
       • Simplest to test 
       • Input produces an output: just assert 
π      • (Not  to be confused with 
       implementation complexity!) 




        Pascal‐Louis Perez, kaChing Group Inc. 
High Level Classification 

     Correctness                   Availability 

λ 
                              • Transformations can only be CPU 
π                             bound 
                              • Timing tests, benchmarking, … 




        Pascal‐Louis Perez, kaChing Group Inc. 
High Level Classification 

     Correctness                   Availability 

λ 

π 
       • Key idea: fake the world 
       • Mocks, stubs, fakes 



        Pascal‐Louis Perez, kaChing Group Inc. 
High Level Classification 

     Correctness                   Availability 

λ 

π 
             • Work in small batches 
             • End‐to‐end tests, regression test, 
             performance lab 
             (Find yourself a great architect!) 


        Pascal‐Louis Perez, kaChing Group Inc. 
Think Outside the Box 
                          C               A 
               λ 
               π 

          A                                                   C    A 
     C 
λ                                                        λ 

π                                                        π 
                           C               A 
               λ 
               π 

               Pascal‐Louis Perez, kaChing Group Inc. 
Repository (or Client) Pattern 

     C    A    @ImplementedBy(DbUserRepo.class)
λ              interface UserRepository {
π                User get(Id<User> id);
               }

               UserRepository repo = ...;
               User pascal = repo.get(Id.<User> of(8));



     C    A    class DbUserRepo
λ                  implements UserRepository {
π                // implementation
               }


                      Pascal‐Louis Perez, kaChing Group Inc. 
Components 
• Software composability is key to test‐driven 
  development 
• Testable software abstracts the control flow; 
  As such is functional by nature 




                 Pascal‐Louis Perez, kaChing Group Inc. 
Examples of Simple Tests 
• Marshalling tests 
• Dealing with time 
• Equivalence tester 




                 Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                               λ 



               Marshalling tests 
                                                               π 




Json.Object o =                     Fail fast 
    TwoLattes.createMarshaller(Trade.class).marshall(...);

assertSameJson(
    object(
         string("id"), number(4),
         string("portfolioId"), NULL,
         string("trade"), string("interest"),
         string("date"), string("2008-07-06"),
         string("toDate"), string("2008-06-06"),
         string("fromDate"), string("2008-07-05"),
         string("longInterest"), number(56.43),
         string("shortInterest"), number(-0.81)),
    o); 



                     Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                               λ 



               Marshalling tests 
                                                               π 




Json.Object o =
    TwoLattes.createMarshaller(Trade.class).marshall(...);

assertSameJson(         Dedicated assertions 
    object(
         string("id"), number(4),
         string("portfolioId"), NULL,
         string("trade"), string("interest"),
         string("date"), string("2008-07-06"),
         string("toDate"), string("2008-06-06"),
         string("fromDate"), string("2008-07-05"),
         string("longInterest"), number(56.43),
         string("shortInterest"), number(-0.81)),
    o); 



                     Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                  λ 



                 Marshalling tests 
                                                                  π 




Json.Object o =
    TwoLattes.createMarshaller(Trade.class).marshall(...);

assertSameJson(                 Descriptive expectation 
    object(
         string("id"), number(4),
         string("portfolioId"), NULL,
         string("trade"), string("interest"),
         string("date"), string("2008-07-06"),
         string("toDate"), string("2008-06-06"),
         string("fromDate"), string("2008-07-05"),
         string("longInterest"), number(56.43),
         string("shortInterest"), number(-0.81)),
    o); 



                        Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                           λ 



            Dealing with time 
                                                           π 




• Use clocks 
  – Provider<DateTime> 
  – Provider<LocalDate> 
• Pass in now or today in business logic 




                 Pascal‐Louis Perez, kaChing Group Inc. 
Time Logic 

@VisibleForTesting
<T> T provideCurrentOrHistorical(
     DateTime date, Provider<T> current, Provider<T> historical) {
   DateTime lastTradeDate = getLastTradeDate();  Time logic is easy 
   boolean isCurrent = date == null                  to test 
       || lastTradeDate == null
       || date.compareTo(lastTradeDate) > 0;
   return isCurrent ? current.get() : historical.get();
} 




                         Pascal‐Louis Perez, kaChing Group Inc. 
Time Logic 

@VisibleForTesting
<T> T provideCurrentOrHistorical(              Higher‐order functions 
     DateTime date, Provider<T> current, Provider<T> historical) {
   DateTime lastTradeDate = getLastTradeDate();
   boolean isCurrent = date == null
       || lastTradeDate == null
       || date.compareTo(lastTradeDate) > 0;
   return isCurrent ? current.get() : historical.get();
} 




                          Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                                 λ 



           Equivalence Tester 
                                                                                 π 




EquivalenceTester.check(                                    Tests 
    asList(                                                  Reflexivity 
        new Isin("abCdEFgHiJK3“),                            Symmetry 
        new Isin("ABCDEFGHIJK3“),                            Transitivity 
        new Isin(“abCDefGHIJK3")),                            hashCode consistency 
    asList(
        new Isin("AU0000XVGZA3"),
        new Isin("AU0000XVGZA3"))); 




                  Pascal‐Louis Perez, kaChing Group Inc. 
Rationale for Database Testing 
•   Accessing the database correctly 
•   O/R properly configured and used 
•   Hand written queries 
•   Optimistic concurrency 




                  Pascal‐Louis Perez, kaChing Group Inc. 
JDBC 
                                                                Global static state 
DriverManager.registerDriver(new org.gjt.mm.mysql.Driver());
Connection conn = DriverManager.getConnection("jdbc:...");
PreparedStatement st = conn.prepareStatement("select ...");
st.setString(1, "...");
ResultSet rs = st.executeQuery();
while (rs.next()) {
  // work
}
rs.close();
st.close();
conn.close(); 




                     Pascal‐Louis Perez, kaChing Group Inc. 
JDBC 

DriverManager.registerDriver(new org.gjt.mm.mysql.Driver());
Connection conn = DriverManager.getConnection("jdbc:...");
PreparedStatement st = conn.prepareStatement("select ...");
st.setString(1, "...");
ResultSet rs = st.executeQuery();
while (rs.next()) {
  // work
}
rs.close();
                                 Low level, stateful API, wide scoping 
st.close();
conn.close(); 




                         Pascal‐Louis Perez, kaChing Group Inc. 
JDBC 

DriverManager.registerDriver(new org.gjt.mm.mysql.Driver());
Connection conn = DriverManager.getConnection("jdbc:...");
PreparedStatement st = conn.prepareStatement("select ...");
st.setString(1, "...");
ResultSet rs = st.executeQuery();
while (rs.next()) {
  // work
}                                                Resources hell 
rs.close();
st.close();
conn.close(); 




                      Pascal‐Louis Perez, kaChing Group Inc. 
Hibernate 
                                                               Global state 
SessionFactory factory = ...;
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
List<User> users = session
    .createQuery("from User where ...")
    .list();
 for (User user : users) {
   // work
 }
 tx.commit();
 session.close(); 




                    Pascal‐Louis Perez, kaChing Group Inc. 
Hibernate 

SessionFactory factory = ...;                                  High‐level API 
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
List<User> users = session
    .createQuery("from User where ...")
    .list();
 for (User user : users) {
   // work
 }
 tx.commit();
 session.close(); 




                    Pascal‐Louis Perez, kaChing Group Inc. 
Hibernate 

SessionFactory factory = ...;
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
List<User> users = session
    .createQuery("from User where ...")
    .list();
 for (User user : users) {
   // work
 }                                                             Resources hell 
 tx.commit();
 session.close(); 




                    Pascal‐Louis Perez, kaChing Group Inc. 
Transacter 
                                                              Global state 
Transacter transacter = ...;
transacter.execute(new WithSession() {
  public void run(Session session) {
     List<User> users = ...;
     for (User user : users) {
       // work
     }
  }
}); 




                   Pascal‐Louis Perez, kaChing Group Inc. 
Transacter 

Transacter transacter = ...;          High‐level API, no resources 
transacter.execute(new WithSession() {
  public void run(Session session) {
     List<User> users = ...;
     for (User user : users) {
       // work
     }
  }
}); 




                      Pascal‐Louis Perez, kaChing Group Inc. 
Transacter 

Transacter transacter = ...;
transacter.execute(new WithSession() {
  public void run(Session session) {  Lexical scoping 
     List<User> users = ...;
     for (User user : users) {
       // work
     }
  }
}); 




                     Pascal‐Louis Perez, kaChing Group Inc. 
Database Testing is Hard 
•   Complex to set up : PersistenceTestRunner 
•   Schema installation : O/R Mapping 
•   Requires data to be loaded : Fixtures, DbUnit 
•   Developer must have proper environment 
    : in‐memory DBs (HSQLDB, Connector/MXJ) 




                  Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                             λ 



         PersistenceTestRunner 
                                                             π 




@RunWith(PersistenceTestRunner.class)     Declarative setup 
@PersistentEntities({Item.class, Note.class})
public class ExamplePersistentTest {

    @Test
    public void example1(Transacter transacter) {
      // work
    }

    @Test
    public void example2() {
      // work
    }

}


                   Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                             λ 



         PersistenceTestRunner 
                                                             π 




@RunWith(PersistenceTestRunner.class)
@PersistentEntities({Item.class, Note.class})
public class ExamplePersistentTest {
                                           Lexical scoping 
  @Test
  public void example1(Transacter transacter) {
    // work
  }

    @Test
    public void example2() {
      // work
    }

}


                   Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                               λ 



         PersistenceTestRunner 
                                                               π 




@RunWith(PersistenceTestRunner.class)
@PersistentEntities({Item.class, Note.class})
public class ExamplePersistentTest {

    @Test                           RuntimeException 
    public void example1(Transacter transacter) {
      // work
    }

    @Test
    public void example2() {
      // work
    }

}


                     Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                 λ 



          PersistenceTestRunner 
                                                                 π 




@RunWith(PersistenceTestRunner.class)
@PersistentEntities({Item.class, Note.class})
public class ExamplePersistentTest {

    @Test
    public void example1(Transacter transacter) {
      // work
    }
                                 Non‐persistent tests run as usual 
    @Test
    public void example2() {
      // work
    }

}


                      Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                            λ 



     Testing Interactions (I/O, …) 
                                                            π 




• Implicit global state 
• Many cases 
  – HTTP GET: succeed, fail to connect, connection 
    closed before headers are read, … 
  – Sending e‐mail: succeed, connection lost after 
    HELO, … 
• Sequencing is crucial 


                  Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                      λ 



   Testing the Transacter (success) 
                                                                      π 




                                                                 Mocking 
final WithSession withSession = mockery.mock(WithSession.class);
mockery.checking(new Expectations() {{
  one(sessionFactory).openSession();
      will(returnValue(session));
      inSequence(execution);
  one(session).connection(); will(...); inSequence(...);
  one(connection).setReadOnly(with(equal(false))); ...
  one(connection).setAutoCommit(with(equal(false))); ...
  one(session).beginTransaction(); inSequence(...);
  ...
}});

transacter.execute(withSession);

mockery.assertIsSatisfied();

                      Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                 λ 



   Testing the Transacter (success) 
                                                                 π 




final WithSession withSession = mockery.mock(WithSession.class);
mockery.checking(new Expectations() {{
  one(sessionFactory).openSession();
                                       Interactions are scripted 
      will(returnValue(session));
      inSequence(execution);
  one(session).connection(); will(...); inSequence(...);
  one(connection).setReadOnly(with(equal(false))); ...
  one(connection).setAutoCommit(with(equal(false))); ...
  one(session).beginTransaction(); inSequence(...);
  ...
}});

transacter.execute(withSession);

mockery.assertIsSatisfied();

                       Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                   λ 



      Testing the Transacter (failure) 
                                                                   π 




mockery.checking(new Expectations() {{
  one(sessionFactory).openSession();
                                        Failure is controlled 
  ...

  one(connection).setReadOnly(with(equal(false)));
      will(throwException(exception));
      inSequence(execution);

  one(session).close(); inSequence(execution);
}});

try {
  transacter.execute(withSession); fail();
} catch (RuntimeException e) {
  assertTrue(e == exception);
}
 mockery.assertIsSatisfied();
                         Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                      λ 



       Testing the Transacter (failure) 
                                                                      π 




mockery.checking(new Expectations() {{
  one(sessionFactory).openSession();
  ...

  one(connection).setReadOnly(with(equal(false)));
      will(throwException(exception));
      inSequence(execution);

  one(session).close(); inSequence(execution);
}});

try {
  transacter.execute(withSession); fail();
} catch (RuntimeException e) {
  assertTrue(e == exception);    Exact  same object (correct bubbling) 
}
 mockery.assertIsSatisfied();
                           Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                                   λ 



      Testing the Transacter (failure) 
                                                                   π 




mockery.checking(new Expectations() {{
  one(sessionFactory).openSession();
  ...

  one(connection).setReadOnly(with(equal(false)));
      will(throwException(exception));
      inSequence(execution);

  one(session).close(); inSequence(execution);
}});
                                     Unreachable program point 
try {
  transacter.execute(withSession); fail();
} catch (RuntimeException e) {
  assertTrue(e == exception);
}
 mockery.assertIsSatisfied();
                         Pascal‐Louis Perez, kaChing Group Inc. 
Meta Tests 
• Cross domain tests to sweep the codebase, 
  exactly like static analysis 
• Catch common mistakes 
      – Distracted developers 
      – Bad APIs 
      – New hires learning conventions 
   


                      Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                           λ 



            Dependency Test 
                                                           π 




• Declare software dependencies 
• Controls layering of application 
• Simpler and more flexible than different 
  compilation units 
• Can guarantee that certain APIs are not used 
  directly 
• Patched Jdepend to parse annotations 


                 Pascal‐Louis Perez, kaChing Group Inc. 
Dependency Test 
dependencies.forPackages(
        "com.kaching.*"
        ).

check("com.kaching.supermap").mayDependOn(
        "com.kaching.platform.guice",
        "org.apache.commons.lang",
        "voldemort.*",
        "org.kohsuke.args4j"
        ).

assertIsVerified(jDepend.getPackages());




                Pascal‐Louis Perez, kaChing Group Inc. 
C    A 
                                                             λ 



                Bad Code Test 
                                                             π 




• Enforce conventions 
• Gotchas, bad APIs 
  – E.g. System.out.println 
  – E.g. java.net.URL 
• Code reviews 
  – Design patterns, custom APIs, etc. 
  – Enforce conventions: automate this! 


                   Pascal‐Louis Perez, kaChing Group Inc. 
Bad Code Test 
@RunWith(BadCodeSnippetsRunner.class)
@CodeSnippets({
@Check(paths = "src/com/kaching", snippets = {

    // no uses of java.net.URL
    @Snippet(value = "bjava.net.URLb", exceptions = {
        "src/com/kaching/...",
        "src/com/kaching/..."
    }),

    // never call default super constructor
    @Snippet("super()")
})})
class MyBadCodeSnippetsTest {




                     Pascal‐Louis Perez, kaChing Group Inc. 
Key Takeaways 
•   Invest in your tests, and testing frameworks 
•   Design patterns to separate concerns 
•   Components 
•   TDD pushes towards functional techniques 
 
•   We’re recruiting jobs@kaching.com 
•   More http://eng.kaching.com 

                   Pascal‐Louis Perez, kaChing Group Inc. 

More Related Content

Similar to Extreme Testing at kaChing

Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java ProgrammersEric Pederson
 
Aaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security TeamsAaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security Teamscentralohioissa
 
Open Source Search: An Analysis
Open Source Search: An AnalysisOpen Source Search: An Analysis
Open Source Search: An AnalysisJustin Finkelstein
 
ScalaCheck
ScalaCheckScalaCheck
ScalaCheckBeScala
 
Algorithm and Programming (Introduction of dev pascal, data type, value, and ...
Algorithm and Programming (Introduction of dev pascal, data type, value, and ...Algorithm and Programming (Introduction of dev pascal, data type, value, and ...
Algorithm and Programming (Introduction of dev pascal, data type, value, and ...Adam Mukharil Bachtiar
 
Boost.Python - domesticating the snake
Boost.Python - domesticating the snakeBoost.Python - domesticating the snake
Boost.Python - domesticating the snakeSławomir Zborowski
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scalashinolajla
 
JavaParser - A tool to generate, analyze and refactor Java code
JavaParser - A tool to generate, analyze and refactor Java codeJavaParser - A tool to generate, analyze and refactor Java code
JavaParser - A tool to generate, analyze and refactor Java codeFederico Tomassetti
 
Alexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudoAlexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudorit2010
 
Jonathan Worthington – Perl 2010 Rit Rakudo
Jonathan Worthington – Perl 2010 Rit RakudoJonathan Worthington – Perl 2010 Rit Rakudo
Jonathan Worthington – Perl 2010 Rit Rakudorit2010
 
Scaling Scala to the database - Stefan Zeiger (Typesafe)
Scaling Scala to the database - Stefan Zeiger (Typesafe)Scaling Scala to the database - Stefan Zeiger (Typesafe)
Scaling Scala to the database - Stefan Zeiger (Typesafe)jaxLondonConference
 
Dealing with combinatorial explosions and boring tests
Dealing with combinatorial explosions and boring testsDealing with combinatorial explosions and boring tests
Dealing with combinatorial explosions and boring testsAlexander Tarlinder
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based TestingC4Media
 
Cascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUGCascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUGMatthew McCullough
 
3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developers3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developersChristopher Batey
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsChristopher Batey
 

Similar to Extreme Testing at kaChing (20)

Scala for Java Programmers
Scala for Java ProgrammersScala for Java Programmers
Scala for Java Programmers
 
Aaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security TeamsAaron Bedra - Effective Software Security Teams
Aaron Bedra - Effective Software Security Teams
 
Kpi driven-java-development-fn conf
Kpi driven-java-development-fn confKpi driven-java-development-fn conf
Kpi driven-java-development-fn conf
 
Open Source Search: An Analysis
Open Source Search: An AnalysisOpen Source Search: An Analysis
Open Source Search: An Analysis
 
ScalaCheck
ScalaCheckScalaCheck
ScalaCheck
 
Algorithm and Programming (Introduction of dev pascal, data type, value, and ...
Algorithm and Programming (Introduction of dev pascal, data type, value, and ...Algorithm and Programming (Introduction of dev pascal, data type, value, and ...
Algorithm and Programming (Introduction of dev pascal, data type, value, and ...
 
Boost.Python - domesticating the snake
Boost.Python - domesticating the snakeBoost.Python - domesticating the snake
Boost.Python - domesticating the snake
 
Scala in Places API
Scala in Places APIScala in Places API
Scala in Places API
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
 
Pattern Matching in Java 14
Pattern Matching in Java 14Pattern Matching in Java 14
Pattern Matching in Java 14
 
JavaParser - A tool to generate, analyze and refactor Java code
JavaParser - A tool to generate, analyze and refactor Java codeJavaParser - A tool to generate, analyze and refactor Java code
JavaParser - A tool to generate, analyze and refactor Java code
 
Alexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudoAlexei shilov 2010 rit-rakudo
Alexei shilov 2010 rit-rakudo
 
Jonathan Worthington – Perl 2010 Rit Rakudo
Jonathan Worthington – Perl 2010 Rit RakudoJonathan Worthington – Perl 2010 Rit Rakudo
Jonathan Worthington – Perl 2010 Rit Rakudo
 
Introducing Kogito
Introducing KogitoIntroducing Kogito
Introducing Kogito
 
Scaling Scala to the database - Stefan Zeiger (Typesafe)
Scaling Scala to the database - Stefan Zeiger (Typesafe)Scaling Scala to the database - Stefan Zeiger (Typesafe)
Scaling Scala to the database - Stefan Zeiger (Typesafe)
 
Dealing with combinatorial explosions and boring tests
Dealing with combinatorial explosions and boring testsDealing with combinatorial explosions and boring tests
Dealing with combinatorial explosions and boring tests
 
An Introduction to Property Based Testing
An Introduction to Property Based TestingAn Introduction to Property Based Testing
An Introduction to Property Based Testing
 
Cascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUGCascading Through Hadoop for the Boulder JUG
Cascading Through Hadoop for the Boulder JUG
 
3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developers3 Dundee-Spark Overview for C* developers
3 Dundee-Spark Overview for C* developers
 
Cassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra ApplicationsCassandra Summit EU 2014 - Testing Cassandra Applications
Cassandra Summit EU 2014 - Testing Cassandra Applications
 

More from Pascal-Louis Perez

Products’ Love Story with Biz
Products’ Love Story with BizProducts’ Love Story with Biz
Products’ Love Story with BizPascal-Louis Perez
 
How to Send a Receipt, Topics in Concurrency and Distributed Systems
How to Send a Receipt, Topics in Concurrency and Distributed SystemsHow to Send a Receipt, Topics in Concurrency and Distributed Systems
How to Send a Receipt, Topics in Concurrency and Distributed SystemsPascal-Louis Perez
 
Developing an Immune System — The Hard and Soft Skills required to avoid Outages
Developing an Immune System — The Hard and Soft Skills required to avoid OutagesDeveloping an Immune System — The Hard and Soft Skills required to avoid Outages
Developing an Immune System — The Hard and Soft Skills required to avoid OutagesPascal-Louis Perez
 
SLL Conf - Continuous Deployment
SLL Conf - Continuous DeploymentSLL Conf - Continuous Deployment
SLL Conf - Continuous DeploymentPascal-Louis Perez
 
Alchemist Startup Primer - Lean Development Practices
Alchemist Startup Primer - Lean Development PracticesAlchemist Startup Primer - Lean Development Practices
Alchemist Startup Primer - Lean Development PracticesPascal-Louis Perez
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedPascal-Louis Perez
 
Xignite's Dedicate kaChing Api
Xignite's Dedicate kaChing ApiXignite's Dedicate kaChing Api
Xignite's Dedicate kaChing ApiPascal-Louis Perez
 

More from Pascal-Louis Perez (12)

Fuchsia RFCs
Fuchsia RFCsFuchsia RFCs
Fuchsia RFCs
 
Products’ Love Story with Biz
Products’ Love Story with BizProducts’ Love Story with Biz
Products’ Love Story with Biz
 
How to Send a Receipt, Topics in Concurrency and Distributed Systems
How to Send a Receipt, Topics in Concurrency and Distributed SystemsHow to Send a Receipt, Topics in Concurrency and Distributed Systems
How to Send a Receipt, Topics in Concurrency and Distributed Systems
 
Corporate Finance Primer
Corporate Finance PrimerCorporate Finance Primer
Corporate Finance Primer
 
Developing an Immune System — The Hard and Soft Skills required to avoid Outages
Developing an Immune System — The Hard and Soft Skills required to avoid OutagesDeveloping an Immune System — The Hard and Soft Skills required to avoid Outages
Developing an Immune System — The Hard and Soft Skills required to avoid Outages
 
SLL Conf - Continuous Deployment
SLL Conf - Continuous DeploymentSLL Conf - Continuous Deployment
SLL Conf - Continuous Deployment
 
Alchemist Startup Primer - Lean Development Practices
Alchemist Startup Primer - Lean Development PracticesAlchemist Startup Primer - Lean Development Practices
Alchemist Startup Primer - Lean Development Practices
 
Database compatibility
Database compatibilityDatabase compatibility
Database compatibility
 
Applying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing SpeedApplying Compiler Techniques to Iterate At Blazing Speed
Applying Compiler Techniques to Iterate At Blazing Speed
 
Type Checking JavaScript
Type Checking JavaScriptType Checking JavaScript
Type Checking JavaScript
 
Xignite's Dedicate kaChing Api
Xignite's Dedicate kaChing ApiXignite's Dedicate kaChing Api
Xignite's Dedicate kaChing Api
 
kaChing's API garage event
kaChing's API garage eventkaChing's API garage event
kaChing's API garage event
 

Recently uploaded

Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsRoshan Dwivedi
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Enterprise Knowledge
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 

Recently uploaded (20)

Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live StreamsTop 5 Benefits OF Using Muvi Live Paywall For Live Streams
Top 5 Benefits OF Using Muvi Live Paywall For Live Streams
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 

Extreme Testing at kaChing

  • 1. Extreme Testing at kaChing  From Commit to Production in 5 minutes    Pascal‐Louis Perez –               .com  Pascal‐Louis Perez, kaChing Group Inc. 
  • 2. kaChing: the Investing Talent Marketplace  • Marketplace for qualified managers  – Young professionals  – RIAs  – Hedge Fund managers  • Customers can mirror “kaChing Geniuses”  – Your own brokerage account  – Real time reporting; Analytics; Drift alerts  • Unparalleled Transparency  – See everything: holdings, risk metrics, trades, …  – Clear fee structure: management fee. No hidden fees,  exit fees, …  Pascal‐Louis Perez, kaChing Group Inc. 
  • 3.   Pascal‐Louis Perez, kaChing Group Inc. 
  • 4. Our System in 30 Seconds  Pascal‐Louis Perez, kaChing Group Inc. 
  • 5. Testing Matters  Architectural Soundness  Delighting Customers  Pascal‐Louis Perez, kaChing Group Inc. 
  • 6. Testable Code Because…  • It allows quick iterations  • It makes it easier to scale the team  • It is more cost effective than debugging  • It obsoletes the need for functional QA  • It facilitates continuous refactoring, allowing  the code to get better with age  • It attracts the right kind of engineers  Pascal‐Louis Perez, kaChing Group Inc. 
  • 7. High Level Classification  Correctness  Availability  λ  π  Pascal‐Louis Perez, kaChing Group Inc. 
  • 8. High Level Classification  Correctness  Availability  λ  • Bad: incorrect  but available system  • Bad: correct but unavailable system  π  Pascal‐Louis Perez, kaChing Group Inc. 
  • 9. High Level Classification  Correctness  Availability  • Transformations (λ)  λ  • Interactions (π): send an e‐mail,  store data in a db, RPC call  • In π implicit global mutable state  π  Pascal‐Louis Perez, kaChing Group Inc. 
  • 10. High Level Classification  Correctness  Availability  λ  • Simplest to test  • Input produces an output: just assert  π  • (Not  to be confused with  implementation complexity!)  Pascal‐Louis Perez, kaChing Group Inc. 
  • 11. High Level Classification  Correctness  Availability  λ  • Transformations can only be CPU  π  bound  • Timing tests, benchmarking, …  Pascal‐Louis Perez, kaChing Group Inc. 
  • 12. High Level Classification  Correctness  Availability  λ  π  • Key idea: fake the world  • Mocks, stubs, fakes  Pascal‐Louis Perez, kaChing Group Inc. 
  • 13. High Level Classification  Correctness  Availability  λ  π  • Work in small batches  • End‐to‐end tests, regression test,  performance lab  (Find yourself a great architect!)  Pascal‐Louis Perez, kaChing Group Inc. 
  • 14. Think Outside the Box  C  A  λ  π  A  C  A  C  λ  λ  π  π  C  A  λ  π  Pascal‐Louis Perez, kaChing Group Inc. 
  • 15. Repository (or Client) Pattern  C  A  @ImplementedBy(DbUserRepo.class) λ  interface UserRepository { π  User get(Id<User> id); } UserRepository repo = ...; User pascal = repo.get(Id.<User> of(8)); C  A  class DbUserRepo λ  implements UserRepository { π  // implementation } Pascal‐Louis Perez, kaChing Group Inc. 
  • 16. Components  • Software composability is key to test‐driven  development  • Testable software abstracts the control flow;  As such is functional by nature  Pascal‐Louis Perez, kaChing Group Inc. 
  • 17. Examples of Simple Tests  • Marshalling tests  • Dealing with time  • Equivalence tester  Pascal‐Louis Perez, kaChing Group Inc. 
  • 18. A  λ  Marshalling tests  π  Json.Object o =  Fail fast  TwoLattes.createMarshaller(Trade.class).marshall(...); assertSameJson( object( string("id"), number(4), string("portfolioId"), NULL, string("trade"), string("interest"), string("date"), string("2008-07-06"), string("toDate"), string("2008-06-06"), string("fromDate"), string("2008-07-05"), string("longInterest"), number(56.43), string("shortInterest"), number(-0.81)), o);  Pascal‐Louis Perez, kaChing Group Inc. 
  • 19. A  λ  Marshalling tests  π  Json.Object o = TwoLattes.createMarshaller(Trade.class).marshall(...); assertSameJson(  Dedicated assertions  object( string("id"), number(4), string("portfolioId"), NULL, string("trade"), string("interest"), string("date"), string("2008-07-06"), string("toDate"), string("2008-06-06"), string("fromDate"), string("2008-07-05"), string("longInterest"), number(56.43), string("shortInterest"), number(-0.81)), o);  Pascal‐Louis Perez, kaChing Group Inc. 
  • 20. A  λ  Marshalling tests  π  Json.Object o = TwoLattes.createMarshaller(Trade.class).marshall(...); assertSameJson(  Descriptive expectation  object( string("id"), number(4), string("portfolioId"), NULL, string("trade"), string("interest"), string("date"), string("2008-07-06"), string("toDate"), string("2008-06-06"), string("fromDate"), string("2008-07-05"), string("longInterest"), number(56.43), string("shortInterest"), number(-0.81)), o);  Pascal‐Louis Perez, kaChing Group Inc. 
  • 21. A  λ  Dealing with time  π  • Use clocks  – Provider<DateTime>  – Provider<LocalDate>  • Pass in now or today in business logic  Pascal‐Louis Perez, kaChing Group Inc. 
  • 22. Time Logic  @VisibleForTesting <T> T provideCurrentOrHistorical( DateTime date, Provider<T> current, Provider<T> historical) { DateTime lastTradeDate = getLastTradeDate();  Time logic is easy  boolean isCurrent = date == null      to test  || lastTradeDate == null || date.compareTo(lastTradeDate) > 0; return isCurrent ? current.get() : historical.get(); }  Pascal‐Louis Perez, kaChing Group Inc. 
  • 23. Time Logic  @VisibleForTesting <T> T provideCurrentOrHistorical(  Higher‐order functions  DateTime date, Provider<T> current, Provider<T> historical) { DateTime lastTradeDate = getLastTradeDate(); boolean isCurrent = date == null || lastTradeDate == null || date.compareTo(lastTradeDate) > 0; return isCurrent ? current.get() : historical.get(); }  Pascal‐Louis Perez, kaChing Group Inc. 
  • 24. A  λ  Equivalence Tester  π  EquivalenceTester.check( Tests  asList(  Reflexivity  new Isin("abCdEFgHiJK3“),  Symmetry  new Isin("ABCDEFGHIJK3“),  Transitivity  new Isin(“abCDefGHIJK3")),   hashCode consistency  asList( new Isin("AU0000XVGZA3"), new Isin("AU0000XVGZA3")));  Pascal‐Louis Perez, kaChing Group Inc. 
  • 25. Rationale for Database Testing  • Accessing the database correctly  • O/R properly configured and used  • Hand written queries  • Optimistic concurrency  Pascal‐Louis Perez, kaChing Group Inc. 
  • 26. JDBC   Global static state  DriverManager.registerDriver(new org.gjt.mm.mysql.Driver()); Connection conn = DriverManager.getConnection("jdbc:..."); PreparedStatement st = conn.prepareStatement("select ..."); st.setString(1, "..."); ResultSet rs = st.executeQuery(); while (rs.next()) { // work } rs.close(); st.close(); conn.close();  Pascal‐Louis Perez, kaChing Group Inc. 
  • 27. JDBC  DriverManager.registerDriver(new org.gjt.mm.mysql.Driver()); Connection conn = DriverManager.getConnection("jdbc:..."); PreparedStatement st = conn.prepareStatement("select ..."); st.setString(1, "..."); ResultSet rs = st.executeQuery(); while (rs.next()) { // work } rs.close();  Low level, stateful API, wide scoping  st.close(); conn.close();  Pascal‐Louis Perez, kaChing Group Inc. 
  • 28. JDBC  DriverManager.registerDriver(new org.gjt.mm.mysql.Driver()); Connection conn = DriverManager.getConnection("jdbc:..."); PreparedStatement st = conn.prepareStatement("select ..."); st.setString(1, "..."); ResultSet rs = st.executeQuery(); while (rs.next()) { // work }  Resources hell  rs.close(); st.close(); conn.close();  Pascal‐Louis Perez, kaChing Group Inc. 
  • 29. Hibernate   Global state  SessionFactory factory = ...; Session session = factory.openSession(); Transaction tx = session.beginTransaction(); List<User> users = session .createQuery("from User where ...") .list(); for (User user : users) { // work } tx.commit(); session.close();  Pascal‐Louis Perez, kaChing Group Inc. 
  • 30. Hibernate  SessionFactory factory = ...;  High‐level API  Session session = factory.openSession(); Transaction tx = session.beginTransaction(); List<User> users = session .createQuery("from User where ...") .list(); for (User user : users) { // work } tx.commit(); session.close();  Pascal‐Louis Perez, kaChing Group Inc. 
  • 31. Hibernate  SessionFactory factory = ...; Session session = factory.openSession(); Transaction tx = session.beginTransaction(); List<User> users = session .createQuery("from User where ...") .list(); for (User user : users) { // work }  Resources hell  tx.commit(); session.close();  Pascal‐Louis Perez, kaChing Group Inc. 
  • 32. Transacter   Global state  Transacter transacter = ...; transacter.execute(new WithSession() { public void run(Session session) { List<User> users = ...; for (User user : users) { // work } } });  Pascal‐Louis Perez, kaChing Group Inc. 
  • 33. Transacter  Transacter transacter = ...;  High‐level API, no resources  transacter.execute(new WithSession() { public void run(Session session) { List<User> users = ...; for (User user : users) { // work } } });  Pascal‐Louis Perez, kaChing Group Inc. 
  • 34. Transacter  Transacter transacter = ...; transacter.execute(new WithSession() { public void run(Session session) {  Lexical scoping  List<User> users = ...; for (User user : users) { // work } } });  Pascal‐Louis Perez, kaChing Group Inc. 
  • 35. Database Testing is Hard  • Complex to set up : PersistenceTestRunner  • Schema installation : O/R Mapping  • Requires data to be loaded : Fixtures, DbUnit  • Developer must have proper environment  : in‐memory DBs (HSQLDB, Connector/MXJ)  Pascal‐Louis Perez, kaChing Group Inc. 
  • 36. A  λ  PersistenceTestRunner  π  @RunWith(PersistenceTestRunner.class)  Declarative setup  @PersistentEntities({Item.class, Note.class}) public class ExamplePersistentTest { @Test public void example1(Transacter transacter) { // work } @Test public void example2() { // work } } Pascal‐Louis Perez, kaChing Group Inc. 
  • 37. A  λ  PersistenceTestRunner  π  @RunWith(PersistenceTestRunner.class) @PersistentEntities({Item.class, Note.class}) public class ExamplePersistentTest {  Lexical scoping  @Test public void example1(Transacter transacter) { // work } @Test public void example2() { // work } } Pascal‐Louis Perez, kaChing Group Inc. 
  • 38. A  λ  PersistenceTestRunner  π  @RunWith(PersistenceTestRunner.class) @PersistentEntities({Item.class, Note.class}) public class ExamplePersistentTest { @Test  RuntimeException  public void example1(Transacter transacter) { // work } @Test public void example2() { // work } } Pascal‐Louis Perez, kaChing Group Inc. 
  • 39. A  λ  PersistenceTestRunner  π  @RunWith(PersistenceTestRunner.class) @PersistentEntities({Item.class, Note.class}) public class ExamplePersistentTest { @Test public void example1(Transacter transacter) { // work }  Non‐persistent tests run as usual  @Test public void example2() { // work } } Pascal‐Louis Perez, kaChing Group Inc. 
  • 40. A  λ  Testing Interactions (I/O, …)  π  • Implicit global state  • Many cases  – HTTP GET: succeed, fail to connect, connection  closed before headers are read, …  – Sending e‐mail: succeed, connection lost after  HELO, …  • Sequencing is crucial  Pascal‐Louis Perez, kaChing Group Inc. 
  • 41. A  λ  Testing the Transacter (success)  π   Mocking  final WithSession withSession = mockery.mock(WithSession.class); mockery.checking(new Expectations() {{ one(sessionFactory).openSession(); will(returnValue(session)); inSequence(execution); one(session).connection(); will(...); inSequence(...); one(connection).setReadOnly(with(equal(false))); ... one(connection).setAutoCommit(with(equal(false))); ... one(session).beginTransaction(); inSequence(...); ... }}); transacter.execute(withSession); mockery.assertIsSatisfied(); Pascal‐Louis Perez, kaChing Group Inc. 
  • 42. A  λ  Testing the Transacter (success)  π  final WithSession withSession = mockery.mock(WithSession.class); mockery.checking(new Expectations() {{ one(sessionFactory).openSession();  Interactions are scripted  will(returnValue(session)); inSequence(execution); one(session).connection(); will(...); inSequence(...); one(connection).setReadOnly(with(equal(false))); ... one(connection).setAutoCommit(with(equal(false))); ... one(session).beginTransaction(); inSequence(...); ... }}); transacter.execute(withSession); mockery.assertIsSatisfied(); Pascal‐Louis Perez, kaChing Group Inc. 
  • 43. A  λ  Testing the Transacter (failure)  π  mockery.checking(new Expectations() {{ one(sessionFactory).openSession();  Failure is controlled  ... one(connection).setReadOnly(with(equal(false))); will(throwException(exception)); inSequence(execution); one(session).close(); inSequence(execution); }}); try { transacter.execute(withSession); fail(); } catch (RuntimeException e) { assertTrue(e == exception); } mockery.assertIsSatisfied(); Pascal‐Louis Perez, kaChing Group Inc. 
  • 44. A  λ  Testing the Transacter (failure)  π  mockery.checking(new Expectations() {{ one(sessionFactory).openSession(); ... one(connection).setReadOnly(with(equal(false))); will(throwException(exception)); inSequence(execution); one(session).close(); inSequence(execution); }}); try { transacter.execute(withSession); fail(); } catch (RuntimeException e) { assertTrue(e == exception);  Exact  same object (correct bubbling)  } mockery.assertIsSatisfied(); Pascal‐Louis Perez, kaChing Group Inc. 
  • 45. A  λ  Testing the Transacter (failure)  π  mockery.checking(new Expectations() {{ one(sessionFactory).openSession(); ... one(connection).setReadOnly(with(equal(false))); will(throwException(exception)); inSequence(execution); one(session).close(); inSequence(execution); }});  Unreachable program point  try { transacter.execute(withSession); fail(); } catch (RuntimeException e) { assertTrue(e == exception); } mockery.assertIsSatisfied(); Pascal‐Louis Perez, kaChing Group Inc. 
  • 46. Meta Tests  • Cross domain tests to sweep the codebase,  exactly like static analysis  • Catch common mistakes  – Distracted developers  – Bad APIs  – New hires learning conventions    Pascal‐Louis Perez, kaChing Group Inc. 
  • 47. A  λ  Dependency Test  π  • Declare software dependencies  • Controls layering of application  • Simpler and more flexible than different  compilation units  • Can guarantee that certain APIs are not used  directly  • Patched Jdepend to parse annotations  Pascal‐Louis Perez, kaChing Group Inc. 
  • 48. Dependency Test  dependencies.forPackages( "com.kaching.*" ). check("com.kaching.supermap").mayDependOn( "com.kaching.platform.guice", "org.apache.commons.lang", "voldemort.*", "org.kohsuke.args4j" ). assertIsVerified(jDepend.getPackages()); Pascal‐Louis Perez, kaChing Group Inc. 
  • 49. A  λ  Bad Code Test  π  • Enforce conventions  • Gotchas, bad APIs  – E.g. System.out.println  – E.g. java.net.URL  • Code reviews  – Design patterns, custom APIs, etc.  – Enforce conventions: automate this!  Pascal‐Louis Perez, kaChing Group Inc. 
  • 50. Bad Code Test  @RunWith(BadCodeSnippetsRunner.class) @CodeSnippets({ @Check(paths = "src/com/kaching", snippets = { // no uses of java.net.URL @Snippet(value = "bjava.net.URLb", exceptions = { "src/com/kaching/...", "src/com/kaching/..." }), // never call default super constructor @Snippet("super()") })}) class MyBadCodeSnippetsTest { Pascal‐Louis Perez, kaChing Group Inc. 
  • 51. Key Takeaways  • Invest in your tests, and testing frameworks  • Design patterns to separate concerns  • Components  • TDD pushes towards functional techniques    • We’re recruiting jobs@kaching.com  • More http://eng.kaching.com  Pascal‐Louis Perez, kaChing Group Inc.