58
The Testing Process CS320 – Fundamentals of Software Engineering

Lecture 18

Embed Size (px)

Citation preview

Page 1: Lecture 18

The Testing Process

CS320 – Fundamentals of Software Engineering

Page 2: Lecture 18

What is Testing?

IEEE:“The process of operating a system or

component under specified condition, observing or recording the results, and making an evaluation of some aspect of the system or component.”

Specified Condition = Test Cases

Page 3: Lecture 18

What is testing?

Rick Craig and Stefan Jaskiel:

“Testing is a concurrent lifecycle process of engineering, using and maintaining testware in order to measure and improve the quality of the software being tested”

Includes planning, analysis, and design that lead to test cases

Page 4: Lecture 18

What is testing?

Testing is the process of comparing “what is” with “what ought to be”

Page 5: Lecture 18

Boris Beizer’s Five Levels

Level 0 – No difference between testing and debugging

Level 1 – Purpose is to show software worksLevel 2 – Purpose is to show that software

doesn’t work (tough cases, boundary values)Level 3 – Purpose is not to prove, but to reduce

the perceived risk of not working at an acceptable value

Level 4 – Mental discipline that result in low risk software (Make software more testable from inception)

Page 6: Lecture 18

Challenges

Not enough time Too many combos Difficult to determine the expected result of

each test Non-existent or rapidly changing req’s No training No tool support Management doesn't understand testing

Page 7: Lecture 18

Test Cases

Need to be designed:Systematic approachDocumentation & PlanningGoal and purpose

Page 8: Lecture 18

Test Case

Inputs Expected Outputs Order of Execution

(and Testing Criteria) how do I know when I’m done testing???

Page 9: Lecture 18

Inputs

DataFiles Interfacing Systems (keyboards, mice

…)databases

Page 10: Lecture 18

Outputs

Excepted Results (oracle)Program, process or dataRegression test suitesValidation dataPurchase test suitesExisting program

Page 11: Lecture 18

Order of Execution

Cascading test cases (build on each other) Ex. Create record in database

• Use record• Delete record etc.

Indecent test case (order does not matter)

Page 12: Lecture 18

Testing Criteria

When do I stop testing:Ex1: When I cover all def use pairsEx2: All paths

Page 13: Lecture 18

Types of Testing

Black BoxReqs and spec, no knowledge of

internal structure White Box

Based on internal paths, structure• Ex1 - definition use pairs

Page 14: Lecture 18

Testing Levels

Unit Testing: smallest piece Integration Testing: assemble pieces

into larger units and test System Testing: all of the software

hardware, user manuals etc. Acceptance Testing: testing, that

when completed will result in delivering the software to the customer

Page 15: Lecture 18

Impossible to Test Everything

int scale(int j){j = j-1; // should be j = j+1j = j/30000;return j;

}

Input range -32768 to 32767 = 65,536 test cases (6 test cases reveal problem)

-30,001, -30000, -1, 0, 29999, 30000

Page 16: Lecture 18

Unit testing with JUnit

Page 17: Lecture 18

One minute summary

‘Code that isn’t tested doesn’t work’Why test?

Code that isn’t regression tested suffers from code rot (breaks eventually)Why regression test?

A unit testing framework help make unit and regression testing more efficient

Page 18: Lecture 18

What is unit testing?

Testing is often divided into categories such as:Unit testing

• Testing a ‘unit’ of code, usually a class

Integration testing• Testing a module of code (e.g. a package)

Application testing• Testing the code as the user would see it

(black box)

Page 19: Lecture 18

What is a testing framework?

A test framework provides reusable test functionality which:Is easier to use (e.g. don’t have to

write the same code for each class)Is standardized and reusableProvides a base for regression tests

Page 20: Lecture 18

Why formalize unit testing?

Unit testing has often been done, but in an ad hoc manner E.g. adding a main method to a class,

which runs tests on the class Axiom:

Code that isn’t tested doesn’t work ‘If code has no automated test case

written for it to prove that it works, it must be assumed not to work.’ (Hightower and Lesiecki)

Page 21: Lecture 18

Why use a testing framework? Each class must be tested when it is

developed Each class needs a regression test Regression tests need to have

standard interfaces Thus, we can build the regression test

when building the class and have a better, more stable product for less work

Page 22: Lecture 18

Regression testing

New code and changes to old code can affect the rest of the code base‘Affect’ sometimes means ‘break’

I need to run tests on the old code, to verify it works – these are regression tests

Regression testing is required for a stable, maintainable code base

Page 23: Lecture 18

Regression Testing

Regression testing - retesting code to check for errors due to changes

Rothermel and Harrold (1994) provide a simple definition for regression testing (T0 = original tests):1. Identify changes to the software2. Evaluate which tests from set T0 are no longer valid

and create a subset T13. Use T1 to test software4. Identify if any parts of the system have not been

tested adequately (based upon test adequacy criteria) and generate a new set of tests T2

5. Use T2 to test software

Page 24: Lecture 18

Regression Testing

Rothermel and Harrold built framework of several retest selection techniques (1996)Minimization

• Linear equationsCoverage

• ID changed definition-use pairs in control flow graphs

Safe techniques• Control dependency graphs.

Page 25: Lecture 18

Background: Regression Testing

Leung and White classify test cases according to reuse (1989). Reusable test cases cover unmodified

code (kept but not used)Retestable test cases cover modified

code (used) Obsolete test-cases cover removed

code (deleted)

Page 26: Lecture 18

Regression Testing

Briand et al. (TR 2004) uses Use Cases, Sequence Diagrams, and Class Diagrams to regression test code.

Creates mapping between design changes and code changes to classify code test cases.

Uses Leung and White approach to classify test cases Makes assumptions regarding how the UML is used:

(1) assumes all possible use-case scenarios can be realized by Sequence Diagrams

(2) assumes that each test case maps to a Sequence Diagram Scenario

Page 27: Lecture 18

Regression testing and refactoring

‘Refactoring is a technique to restructure code in a disciplined way.’ (Martin Fowler)

Refactoring is an excellent way to break code.

Regression testing allows developers to refactor safely – if the refactored code passes the test suite, it works

Page 28: Lecture 18

Running automated tests

The real power of regression tests happens when they are automated This requires they report pass/fail results in a

standardized way Can set up jobs to

Clean & check out latest build tree Run tests Put results on a web page & send mail (if tests

fail) JUnit & ant have code to do all of this

Page 29: Lecture 18

Some background

eXtreme programming (XP) is a ‘programming methodology that stresses (among other things) testing and refactoring

The Apache community provides open-source software, including the Jakarta project (server side java tools, e.g. tomcat (servlet engine))

Ant is a build tool (like make) Part of the Jakarta project Is becoming the de facto standard for java projects Is written in java, uses xml to specify build targets

Page 30: Lecture 18

What is Junit?

JUnit is a regression testing framework written by Erich Gamma and Kent Beck

It is found at www.junit.org It consists of classes that the developer

can extend to write a test Notably: junit.framework.TestCase

and related structure to run and report the tests

Page 31: Lecture 18

JUnit..

JUnit helps the programmer:Define and execute tests and test

suitesFormalize requirements and clarify

architectureWrite and debug codeIntegrate code and always be ready to

release a working version

Page 32: Lecture 18

Installing Junit and CppUnit

For JUnit Download (and unpack) the distribution Put the jar file on your classpath

For CppUnit Download (and unpack) the distribution On linux, run make (configure; make; make

install) Bob Goddard figured out the required

switches on Solaris, contact Bob, Pete Brodsky or I for details

Page 33: Lecture 18

Tool integration

Java IDEsNetbeans -

http://www.netbeans.org/index.html• Claims to include Junit integrationIt’s

freeIdea - http://www.intellij.com/idea/

• Includes the Junit jar & is Junit savvy• Also supports ant• Not free, but not expensive ($400-

$600)

Page 34: Lecture 18

What JUnit does

JUnit runs a suite of tests and reports results

For each test in the test suite:JUnit calls setUp()

• This method should create any objects you may need for testing

Page 35: Lecture 18

What JUnit does…

JUnit calls one test method• The test method may comprise multiple test

cases; that is, it may make multiple calls to the method you are testing

• In fact, since it’s your code, the test method can do anything you want

• The setUp() method ensures you entered the test method with a virgin set of objects; what you do with them is up to you

JUnit calls tearDown()• This method should remove any objects you

created

Page 36: Lecture 18

Creating a test class in JUnit

Define a subclass of TestCase Override the setUp() method to initialize object(s)

under test. Override the tearDown() method to release object(s)

under test. Define one or more public testXXX() methods that

exercise the object(s) under test and assert expected results.

Define a static suite() factory method that creates a TestSuite containing all the testXXX() methods of the TestCase.

Optionally define a main() method that runs the TestCase in batch mode.

Page 37: Lecture 18

Fixtures

A fixture is just a some code you want run before every test

You get a fixture by overriding the method protected void setUp() { …}

The general rule for running a test is:protected void runTest() {

setUp(); <run the test> tearDown();}

so we can override setUp and/or tearDown, and that code will be run prior to or after every test case

Page 38: Lecture 18

Implementing setUp() method

Override setUp() to initialize the variables, and objects

Since setUp() is your code, you can modify it any way you like (such as creating new objects in it)

Reduces the duplication of code

Page 39: Lecture 18

Implementing the tearDown() method

In most cases, the tearDown() method doesn’t need to do anythingThe next time you run setUp(), your

objects will be replaced, and the old objects will be available for garbage collection

Like the finally clause in a try-catch-finally statement, tearDown() is where you would release system resources (such as streams)

Page 40: Lecture 18

The structure of a test method

A test method doesn’t return a result If the tests run correctly, a test method

does nothing If a test fails, it throws an

AssertionFailedError The JUnit framework catches the error

and deals with it; you don’t have to do anything

Page 41: Lecture 18

Test suites

In practice, you want to run a group of related tests (e.g. all the tests for a class)

To do so, group your test methods in a class which extends TestCase

Running suites we will see in examples

Page 42: Lecture 18

assertX methods

static void assertTrue(boolean test) static void assertFalse(boolean test) assertEquals(expected, actual) assertSame(Object expected,

Object actual) assertNotSame(Object expected,

Object actual) assertNull(Object object)

Page 43: Lecture 18

assertX methods

assertNotNull(Object object) fail() All the above may take an optional String

message as the first argument, for example,static void assertTrue(String message, boolean test)

Page 44: Lecture 18

Organize The Tests

Create test cases in the same package as the code under test

For each Java package in your application, define a TestSuite class that contains all the tests for validating the code in the package

Define similar TestSuite classes that create higher-level and lower-level test suites in the other packages (and sub-packages) of the application

Make sure your build process includes the compilation of all tests

Page 45: Lecture 18

JUnit framework

Testing client

run(TestResult)setUp()runTest()tearDown()

TestCase

fName

setUp()runTest()tearDown()test1()test2()

ConcreteTestCase

action()

TestedClass

setUp()runTest()tearDown()

TestResult

runTest()test1()ortest2()

Test

run(TestResult)addTest(Test)

TestSuite

fTests

forall test in fTests test.run(TestResult)

Page 46: Lecture 18

Writing a test

Directions can be found in the Junit cookbook - http://junit.sourceforge.net/doc/cookbook/cookbook.htm

Summary1. Create an instance of TestCase:

2. Write methods which run your tests, calling them test<Foo>

3. Call a test runner with your test

4. When you want to check a value, call an assert method (e.g. assertTrue()) and pass a condition that is true if the test succeeds

Page 47: Lecture 18

Example: Counter class

For the sake of example, we will create and test a trivial “counter” class The constructor will create a counter and

set it to zero The increment method will add one to the

counter and return the new value The decrement method will subtract one

from the counter and return the new value

Page 48: Lecture 18

Example: Counter class

We write the test methods before we write the codeThis has the advantages described earlierDepending on the JUnit tool we use, we

may have to create the class first, and we may have to populate it with stubs (methods with empty bodies)

Don’t be alarmed if, in this simple example, the JUnit tests are more code than the class itself

Page 49: Lecture 18

JUnit tests for Counter

public class CounterTest extends junit.framework.TestCase { Counter counter1;

public CounterTest() { } // default constructor

protected void setUp() { // creates a (simple) test fixture counter1 = new Counter(); }

protected void tearDown() { } // no resources to release

Page 50: Lecture 18

JUnit tests for Counter…

public void testIncrement() { assertTrue(counter1.increment() == 1); assertTrue(counter1.increment() == 2); }

public void testDecrement() { assertTrue(counter1.decrement() == -1); }} // End from last slide

Page 51: Lecture 18

The Counter class itself

public class Counter {int count = 0;public int increment() { return ++count;}public int decrement() { return --count;}

public int getCount() { return count; }}

Page 52: Lecture 18

Result

We will see with the help of tool

When ??

!! Now !!

Page 53: Lecture 18

Why JUnit

Allow you to write code faster while increasing quality

Elegantly simple Check their own results and provide immediate

feedback Tests is inexpensive Increase the stability of software Developer tests Written in Java Free Gives proper uniderstanding of unit testing

Page 54: Lecture 18

Problems with unit testing

JUnit is designed to call methods and compare the results they return against expected resultsThis ignores:

• Programs that do work in response to GUI commands

• Methods that are used primary to produce output

Page 55: Lecture 18

Problems with unit testing…

I think heavy use of JUnit encourages a “functional” style, where most methods are called to compute a value, rather than to have side effectsThis can actually be a good thingMethods that just return results,

without side effects (such as printing), are simpler, more general, and easier to reuse

Page 56: Lecture 18

Junit addons

Junit has a bunch of add on stuff that has been written for it (your mileage may vary)

Examples Code generators – make guesses at what

tests are needed Load testers Code coverage Testers for thread safety ‘Helpful classes’ (e.g. RecursiveTestSuite is a

TestSuite that will recursively walk through the directory structure looking for subclasses of TestCase and will add them.)

Page 57: Lecture 18

Cactus, HttpUnit, Mock Objects

Cactus (from jakarta) is a simple test framework for unit testing server-side java code (Servlets, EJBs, Tag Libs, Filters, ...).

HttpUnit emulates the relevant portions of browser behavior to allow automated testing (on sourceforge)

Mock objects emulate objects from other parts of the application, but have controlled behaviour

Page 58: Lecture 18

Resources

Web sites Junit - http://www.junit.org CppUnit - http://cppunit.sourceforge.net/ Ant - http://jakarta.apache.org/ant/index.html