Recent Changes - Search:

Software Engineering

This website demonstrates using wikis as teaching and learning tool.

The course instructor is also happy to share the teaching materials here with those who find it readable.

Software Testing - Part 2

A Software Engineering Lecture by Steven Choy

Lecture Overview:

In this lecture, we will continue to learn Software Testing. It covers System Testing, Regression Testing, and Documenting Testing. We will also have a brief touch on how JUnit is used to automate unit testing in Java.

While unit and integration testing focus on finding faults in individual components and the interfaces between the components, system testing ensures that the complete system complies with the functional and nonfunctional requirements. System testing includes functional testing, performance testing, pilot testing, acceptance testing, and installation testing.

Regression testing is to ensure that a program has not regressed; the functionality that was working yesterday is still working today. In other word, regression testing is to ensure that we do not introduce new bugs while removing existing bugs. A program still works correctly after changes were made to it.

Reading: Chapter 11 of the textbook Testing


System Testing

System Testing Overview

  • System testing ensures the system, as a whole, complies with both functional and non-functional requirements
  • Activities involves:
    • Functional Testing
    • Performance Testing
    • Pilot Testing
    • Acceptance Testing
    • Installation Testing

Functional Testing

  • Also known as Requirement Testing
  • As the name reveals, it checks if the system conforms with the functional requirement
  • Test cases are identified from use case model and requirement specification

Performance Testing

  • What are our goals?
    • Check if our system performance meets user's requirement
    • Find out the details of the system in terms of the following metrics:
      • Throughput (no. of request/sec)
      • CPU/Memory/IO/Network Utilization
      • Maximum number of client/request it can handle before breaking the system
      • Time for fail-over of systems
      • Security level (How vulnerable is our system for attack?)
      • etc
  • Load Testing
    • Load the system with an expected number of data/request and check if the system can handle
  • Stress Testing
    • Push the system beyond the limit to evaluate its robustness
    • Load the system with an unreasonable large number of request/data, trying to stress the system to the breaking point
  • Timing Testing
    • Attempt to find behaviours that violate timing constraints described by the non-functional requirement
  • Security Testing
    • Try to find out the security flaws of the system
  • Recovery Testing
    • Evaluates the ability of the system to recover from erroneous state (e.g. hardware/network failure)

Performance Test Tools

  • ApacheBench from Apache HTTP server
  • Rational Performance Tester from IBM (Website)
  • LoadRunner from Mercury (Website)
  • QALoad from Compuware (Website)

Acceptance Testing

  • Does your client accept the system? Acceptance Testing
    • Acceptance testing is performed by clients, not developers
    • The client designs and performs series of tests to check if it conforms with the requirement
  • Typically, majority of bugs are found during this stage (WHY?)
  • Besides, after trying out the system, clients may request for change of requirement in this stage

Pilot Testing

  • Pilot testing is "Let end-users really try out the system before its official release"

Software release life cycle

Does Testing end Here?

Regression Testing

  • Object-oriented software development is an iterative process
  • Fix one bug may introduce another bug somewhere in the code
  • Adding/modifying a feature may also introduce side effect to the existing code
  • A system that fails after the modification of a component is said to be regress
  • Tests that try to produce such failure ⇒ Regression Test
  • Regression testing is testing that a program has not regressed; the functionality that was working yesterday is still working today. In other word, regression testing is to ensure that we do not introduce new bugs while removing existing bugs. A program still works correctly after changes were made to it.
  • So, what's the best way to ensure the modified component does not introduce side effect to the existing system?
    • Retest the whole system with all the test cases!
  • Strategies to streamline the process:
    • Retest dependent components
    • Retest risky components
    • Retest frequently-used components
"Yes, I admit Regression Testing is crucial to our system"
But…
How can we perform all test cases again & again manually?
It's really time-consuming & a waste of development man-hours

Automate Your Testing

  • Unit/Integration Test Automation
    • JUnit – an open-sourced test framework for Java
    • Latest version is 4.0 but we only focus on v3.8
  • User Interface Testing Automation
    • QARun from Compuware
    • QuickTest from Mercury
    • Rational Robot from IBM (website)
    • AutomatedQA

A Very Simple Example

public class Calculator {

    public Calculator() {
    }

    public int add(int num1, int num2) {
        return num1 + num2;
    }

    public int minus(int num1, int num2) {
        return num1 - num2;
    }

}

Unit Test in a manual way

  • If you need to perform unit testing on that piece of code, you probably do it using "System.out"…

public class ManualTestCalculator {

    public static void main(String[] args) {
        Calculator calculator = new Calculator();
        int result = calculator.add(100, 200);
        System.out.println("Result for (100+200) = " + result);
        result = calculator.minus(200, 100);
        System.out.println("Result for (200-100) = " + result);
    }

}

  • Console Output

Result for (100+200) = 300
Result for (200-100) = 100

Automate Unit Testing by JUnit

  • JUnit is developed to automate unit testing in Java
  • A regression testing framework, written by Erich Gamma and Kent Beck

JUnit Example

import junit.framework.*;

public class CalculatorTest extends TestCase {

    private Calculator calculator = null;

    public CalculatorTest(String name) {
        super(name);
    }

    protected void setUp() {
        calculator = new Calculator();
    }

    public static Test suite() {
        TestSuite suite = new TestSuite(CalculatorTest.class);
        return suite;
    }

    /** Test of add method, of class Calculator */
    public void testAdd()  {
        /* Test case #1: Adding two positive integers together */
        int result = calculator.add(100, 200);
        assertEquals(300, result);

        /* Test case #2: Adding two negative integers together */
        result = calculator.add(-100, -200);
        assertEquals(-300, result);
    }

    /** Test of minus method, of class Calculator */
    public void testMinus()  {
        /* Test case #1: Subtract two positive integers */
        int result = calculator.minus(200, 100);
        assertEquals(100, result);

        /* Test case #2: Subtract two negative integer */
        result = calculator.minus(-200, -100);
        assertEquals(-100, result);
    }

}

Unit Testing Quotes

  • Unit tests can be tedious to write, but they save you time in the future by catching bugs after changes [William Wake]

JUnit References

Test Documentation

  • Test Plan
    • Describe what to test
    • A document describes what to be tested, the scope, approach, resources and schedule of the test
  • Sample Test Plan Outline
    1) Test Plan Identifier
    2) References
    3) Introduction
    4) Test Items
    5) Software Risk Issues
    6) Features to be Tested
    7) Features not to be Tested
    8) Approach
    9) Item Pass/Fail Criteria
    10) Suspension Criteria and Resumption Requirements
    11) Test Deliverables
    12) Remaining Test Tasks
    13) Environmental Needs
    14) Staffing and Training Needs
    15) Responsibilities
    16) Schedule
    17) Planning Risks and Contingencies
    18) Approvals
    19) Glossary
  • Test Specification
    • Describe how to test
    • Describe how each test case is run
  • Sample Test Specification Outline
Test case ID
Purpose
What are the test items? Basically what items are you testing? If in same document as above, then a simple 2 line overview and reference to previous document is sufficient for our purpose.
Source of the feature
Who originated the this test case?
Programmer ID
Who programmed the code implementing the feature?
Environmental Setup
Any special procedures required for the individual tests?
Test design method
What techniques has been used? What coverage criterion will be met? Did you use [J/Cpp]Unit? How do you organize the test cases using [J/Cpp]Unit? Many test cases differ only in a few parameters (.e. shelf/slot). These should be parameterized with [J/Cpp]Unit and invoked as needed. Also, there would be some type of system startup (initialize system to a known state and then a tear down part - restore system to initial state after test), that should be found in each TestFixture.
Test case dependencies
What are the test cases whose successful outcome is a precondition for this to be executed? Will the running of one test case possibly interfere with the running of another test case? If yes, identify the cases and state the effects/resolution. For example running a stress test with reduced resources may leave the system in state that may interfere with other test cases.
Test case behaviour
  • Test Report
    • Present the test result

Extra Materials about Software Testing

Suggested Readings on JUnit:

Some Tools for Performance Testing:

Some Tools for Testing Automation

Other useful resources:

On-demand testing via a global community of professional testers - Build your own virtual testing team on demand, define your testing requirements and get real-time valuable bug reporting and application feedback from the uTester global community. Test and release your software with confidence to accelerate time to market.
Watch a Demo (about 3 minutes) (See how our Community of Professional Testers can improve your software testing!)
Application test tools include Source Test Tools, Functional Test Tools, Performance Test Tools, Java Test Tools, Embedded Test Tools, and Database Test Tools.
Opensourcetesting.org aims to boost the profile of open source testing tools within the testing industry, principally by providing users with an easy to use gateway to information on the wide range of open source testing tools available.
35 Performance test tools, including Apache JMeter, benerator, WebLOAD, Grinder, and Siege.
Selenium is a test tool for web applications. Selenium tests run directly in a browser, just as real users do. And they run in Internet Explorer, Mozilla and Firefox on Windows, Linux, and Macintosh. No other test tool covers such a wide array of platforms.
The Grinder is a Java load testing framework that makes it easy to run a distributed test using many load injector machines. It is freely available under a BSD-style open-source license.
Apache JMeter is a 100% pure Java desktop application designed to load test functional behavior and measure performance. It was originally designed for testing Web Applications but has since expanded to other test functions.
In the last few years, unit testing has emerged as one of the Good Ideas of our craft. Support for this has grown to as near to unanimous as you could ask for. The last idea that reached this level of consensus was source control in the mid 90s, something that has obviously stuck around. Unit testing very well may be one of the lasting ideas of this decade.

Thanks for Reading

If you would rather like to have this lecture note in printed format, please click the print action link in the top right corner.

If you find any problem in this lecture note, please feel free to tell Steven by steven@findaway.hk

Edit - History - Print - Recent Changes - Search
Page last modified on September 09, 2009, at 11:03 PM