Slide 1

Slide 1 text

Not sure if I have to check out this problem Or just wait for the customer feedback How to Narrow Down What to Test @ZsoltFabok http://zsoltfabok.com/ #xp2013 http://xp2013.org/ by Zsolt Fabok 2013-06-05

Slide 2

Slide 2 text

@ZsoltFabok or #xp2013

Slide 3

Slide 3 text

Exercise 0: Setup

Slide 4

Slide 4 text

Download putty.exe if you are using windows: http://:8080/xp2013/putty.exe Log in (user, userpass): ssh user@ -p 3022 Create your environment: $ cd xp2013 $ mkdir $ cp -r arithmetic.expression.evaluator $ cd /arithmetic.expression.evaluator $ ant init

Slide 5

Slide 5 text

Check the source directory in your browser: http://:8080/xp2013/

Slide 6

Slide 6 text

“I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don’t typically make a kind of mistake (like setting the wrong variables in a constructor), I don’t test for it. I do tend to make sense of test errors, so I’m extra careful when I have logic with complicated conditionals. When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong.” Kent Beck - September 10, 2010 quote: http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests/153565#153565

Slide 7

Slide 7 text

I’d like to [re]start working on this legacy application

Slide 8

Slide 8 text

My “where to start” list

Slide 9

Slide 9 text

#1 Determine which parts of the code are really used

Slide 10

Slide 10 text

The good old Standish Group Study 7% 13% 16% 19% 45% Always Often Sometimes Rarely Never

Slide 11

Slide 11 text

The goal is to find those features which are always or often used. By studying coverage, access logs, traces, web analytics, heat maps, etc.

Slide 12

Slide 12 text

Let’s have a look at the coverage (using instrumented class files): % cp jetty/cobertura.ser web.ser % cp uploader/cobertura.ser ant.ser % ant usage_coverage usage_coverage: [cobertura-merge] Cobertura: Loaded information on 12 classes. [cobertura-merge] Cobertura: Loaded information on 11 classes. [cobertura-merge] Cobertura: Saved information on 16 classes. [cobertura-report] Cobertura: Loaded information on 16 classes. [cobertura-report] Report time: 600ms BUILD SUCCESSFUL Total time: 2 seconds

Slide 13

Slide 13 text

Example #1: overview

Slide 14

Slide 14 text

Example #2: execution not even executed

Slide 15

Slide 15 text

Example #3: number of execution .NET wins

Slide 16

Slide 16 text

FileBasedMetadata (usage) FileHelper (usage)

Slide 17

Slide 17 text

Exercise 1: Usage

Slide 18

Slide 18 text

Run the application: $ run.sh “4+3” Turn on data collection: $ ant instrument $ vi run.sh Run the application a couple of times: $ run.sh “4+3” Generate report: $ ant usage_report

Slide 19

Slide 19 text

#2 Find out which parts of the code change often

Slide 20

Slide 20 text

By checking how many times a file has been committed into VCS: % ./git_stat.sh 14, VerifierTask.java 13, index.jsp 11, FileBasedUserHome.java 11, FileBasedUser.java 11, FileBasedContentTracker.java 8, IntegrityCheckTask.java 7, MailSender.java

Slide 21

Slide 21 text

FileBasedMetadata (usage) FileHelper (usage) VerifierTask (changes) index.jsp (changes) FileBasedUserHome (changes)

Slide 22

Slide 22 text

Exercise 2: Have a beer (or tea of coffee) :-)

Slide 23

Slide 23 text

#3 Determine which part of the code changes data

Slide 24

Slide 24 text

Code review “You have exactly 1 minute to explain to me what that method does!”

Slide 25

Slide 25 text

FileBasedMetadata (usage) FileHelper (usage, review) VerifierTask (changes) index.jsp (changes) FileBasedUserHome (changes, review) FileBasedContentTracker (review)

Slide 26

Slide 26 text

Exercise 3: Code Review

Slide 27

Slide 27 text

Check the code in the reports directory in your browser: http://:8080/xp2013//.../target/ reports/src

Slide 28

Slide 28 text

#4 Determine where the code is most likely going to fail (e.g. with static code checkers)

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

PMD is not helpful at the moment, but good to know about it

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

FileBasedMetadata (usage) FileHelper (usage, review, bugs) VerifierTask (changes) index.jsp (changes) FileBasedUserHome (changes, review) FileBasedContentTracker (review, bugs) HarversterTask (bugs) FileBasedContentTracker.fsck() (crap4j) FileBasedContentTracker.gc() (crap4j) VerifierTask.execute() (crap4j)

Slide 33

Slide 33 text

Let’s order our list and we are done!

Slide 34

Slide 34 text

FileBasedMetadata (usage) FileHelper (usage, review, bugs) VerifierTask (changes) index.jsp (changes) FileBasedUserHome (changes, review) FileBasedContentTracker (review, bugs) HarversterTask (bugs) FileBasedContentTracker.fsck() (crap4j) FileBasedContentTracker.gc() (crap4j) VerifierTask.execute() (crap4j)

Slide 35

Slide 35 text

Exercise 4: Code Checkers

Slide 36

Slide 36 text

Check the reports directory in your browser: http:///xp2013//.../target/reports Generate reports: $ ant reports

Slide 37

Slide 37 text

Now we know where to start, and now let’s talk about how to start.

Slide 38

Slide 38 text

Gaining 30% coverage in 2 minutes: public class CheaterTest { @Test public void shouldIncreaseTheCoverage() { HarvesterTask harvester = new HarvesterTask(); Project project = new Project(); project.setBaseDir(new File(".")); harvester.setProject(project); harvester.setRepository("../repository"); harvester.setHistory("history"); harvester.setTemplate("templates"); harvester.execute(); } } Covered code != Tested code

Slide 39

Slide 39 text

So, you start with an assertion: public class FileHelperTest { @Test public void shouldReturnTheContentOfAFile() throws IOException { assertEquals("", FileHelper.getFileContent(null)); } } ➡ The ‘assertEquals’ makes sure that your test actually does something ➡ The ‘null’ parameter - along with the NullPointerException - will show you where to continue

Slide 40

Slide 40 text

First test case is done: public class FileHelperTest { @Test public void shouldReturnTheContentOfAFile() throws IOException { File input = File.createTempFile("foo", "bar"); assertEquals("", FileHelper.getFileContent(input)); } } ➡ Now the test is green, let’s continue with a more meaningful test case

Slide 41

Slide 41 text

Now we have two test cases: public class FileHelperTest { @Test public void shouldReturnTheContentOfAFile() throws IOException { File input = File.createTempFile("foo", "bar"); assertEquals("", FileHelper.getFileContent(input)); } @Test public void shouldReturnTheContentOfAFile() throws IOException { File input = File.createTempFile("foo", "bar"); new FileOutputStream(input).write("something".getBytes()); assertEquals("something", FileHelper.getFileContent(input)); } } ➡ Test method names remains the same until the body is filled properly

Slide 42

Slide 42 text

And we are done (assertion + coverage): public class FileHelperTest { private File input; @Before public void setUp() throws IOException { input = File.createTempFile("foo", "bar"); } @Test public void shouldReturnAnEmptyStringForAnEmptyFile() throws IOException { assertEquals("", FileHelper.getFileContent(input)); } @Test public void shouldReturnTheContentOfAFile() throws IOException { setInputFileContent("something"); assertEquals("something", FileHelper.getFileContent(input)); } private void setInputFileContent(String content) throws IOException { new FileOutputStream(input).write("something".getBytes()); } }

Slide 43

Slide 43 text

Exercise 5: Writing tests

Slide 44

Slide 44 text

Get test coverage (also runs tests): $ ant cobertura Run tests: $ ant test If you don’t want to write tests, you can find examples in this folder: samples

Slide 45

Slide 45 text

Well tested code Well tested code everywhere

Slide 46

Slide 46 text

What about web applications? (I’ll use a ruby on rails example, but the principles apply to other frameworks as well)

Slide 47

Slide 47 text

#2 Find out which parts of the code change often (a.k.a VCS statistics) #3 Determine which part of the code changes data (a.k.a code review) Points are just the same. and

Slide 48

Slide 48 text

A large variety of tools are available for: #4 Determine where the code is most likely going to fail (a.k.a static code checkers)

Slide 49

Slide 49 text

% gem install rails_best_practices % rails_best_practices -html .

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

Everything is nice and straightforward until now, but the last remaining point is tricky: #1 Determine which parts of the code are really used (a.k.a. coverage)

Slide 53

Slide 53 text

We can have coverage data in Ruby on Rails, too: ~/Temp/repos/sample_app % gem install simplecov ~/Temp/repos/sample_app % cat script/rails #!/usr/bin/env ruby require 'simplecov' SimpleCov.start do add_group "Models", "app/models" add_group "Controllers", "app/controllers" end APP_PATH = File.expand_path('../../config/application', __FILE__) # rest of the script/rails script

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

There is only one problem: the application must be stopped in order to get the report, which is not really efficient and user friendly.

Slide 56

Slide 56 text

Fortunately, we can use a metric called ‘funnel’:

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

1. This is a huge lost in visitors, would be good to know why. 2. Users visit this page more often than the other page.

Slide 59

Slide 59 text

Slides: http://zsoltfabok.com/speaking/ Code: https://github.com/ZsoltFabok/ arithmetic.expression.evaluator/tree/xp2013/

Slide 60

Slide 60 text

Thank you very much for your attention! http://zsoltfabok.com/ @ZsoltFabok