CSC/ECE 517 Fall 2010/ch6 6b yc

From Expertiza_Wiki
Jump to navigation Jump to search
Support for Assertions in Various O-O Programming Languages


Problem Statement

"Compare the support for assertions in various o-o programming languages. How well is it integrated with the language (instead of being supplied by libraries)? How many kinds of assertions are supported? How are assertions used in the various flavors of xUnit testing frameworks?"


Introduction

Definition

"An imperfect solution is better than none. - B. Meyer "[1]

Assertions are formal constraints on software systems which are inserted as annotations in the source program text. They had their origin in program verification [2]. Program correctness is usually defined in relation to a specification and assertions can encode the semantic properties of a specification. Using assertions to show program correctness is in general a non-trivial task and therefore it is hardly followed in practice. However, many key properties of a program can still be encoded in a simple assertion language. In such a scenario, if a program executes without any assertion violation, it can give some confidence about the program’s correctness. In a sense, assertions test a program without using any test data.

Example

Following is a simple example of an assertion in Java.

int total = NumberOfUsers();
if (total % 2 == 0) {
    // total is even
} else {
    // total is odd
    assert(total % 2 == 1);
}

In Java, % is the remainder operator (or modulus) — if its first operand is negative, the result can also be negative. Here, we have assumed that total is non-negative, so that the remainder of a division with 2 will always be 0 or 1. The assertion makes this assumption explicit — if NumberOfUsers does return a negative value, the program may have a bug.

Different Types of Assertions

Assertions are meant to encode the key properties of O-O programs. They can be classified into the following types.

  • Preconditions: This defines what must be true when a method is invoked.
  • Postconditions: This defines what must be true after a method completes successfully.
  • Class invariants: This defines what must be true about each instance of a class.


Support for Assertions in Various O-O Programming Languages

Assertions in O-O programming languages are either evaluated at compile time or at run time, depending on the concrete programming language [3]. In this section, we will investigate the support for assertions in various O-O programming languages.

Java

Each assertion in Java contains a boolean expression that we believe will be true when the assertion executes. If it is not true, the system will throw an error. By verifying that the boolean expression is indeed true, the assertion confirms our assumptions about the behavior of the program.

The assertion statement in Java has two forms [4]. The first, simpler form is:

assert Expression1 ;

where Expression1 is a boolean expression. When the system runs the assertion, it evaluates Expression1 and if it is false throws an AssertionError with no detail message.

The second form of the assertion statement is:

assert Expression1 : Expression2 ;

where:

  • Expression1 is a boolean expression.
  • Expression2 is an expression that has a value.

Use this version of the assert statement to provide a detail message for the AssertionError. The system passes the value of Expression2 to the appropriate AssertionError constructor, which uses the string representation of the value as the error's detail message.

Here is an example of using assertion in Java.

import java.util.*;
import java.util.Scanner;
  
public class AssertionExample
{
	public static void main( String args[] )
	{
		Scanner scanner = new Scanner( System.in );
		System.out.print( "Enter a number between 0 and 20: " );
		int value = scanner.nextInt();
		assert value >= 0 && value <= 20 : "Invalid number: " + value;
		System.out.printf( "You have entered %d\n", value );
	}
}

In the above example, When the user enters the number scanner.nextInt() method reads the number from the command line. The assert statement determines whether the entered number is within the valid range. If the user entered a number which is out of range then the error occurs.

Ruby

In Ruby, each assertion gives us a way of specifying a desired result or outcome and a way of passing in the actual outcome. If the actual does not equal the expected, the assertion outputs a nice message and records the fact as a failure [5]. There are a bunch of assertion syntax in Ruby Test::Unit. Here, we list some syntax of using assertions in Ruby.

assert(boolean, [ message ] )
# Fails if boolean is false or nil.

assert_nil(obj, [ message ] )
assert_not_nil(obj, [ message ] )
# Expects obj to be (not) nil.

assert_equal(expected, actual, [ message ] )
assert_not_equal(expected, actual, [ message ] )
# Expects obj to equal/not equal expected, using ==.

Here is an example of using assertion in Ruby Test::Unit.

First create a new class.

class SimpleNumber
 
  def initialize( num )
    raise unless num.is_a?(Numeric)
    @x = num
  end
 
  def add( y )
    @x + y
  end
 
  def multiply( y )
    @x * y
  end
 
end

Then we are going to test the SimpleNumber class.

require "simpleNumber"
require "test/unit"
 
class TestSimpleNumber < Test::Unit::TestCase
  def test_simple
    assert_equal(4, SimpleNumber.new(2).add(2) )
    assert_equal(6, SimpleNumber.new(2).multiply(3) )
  end
end

which will produce

>> ruby tc_simpleNumber.rb
Loaded suite tc_simpleNumber
Started
.
Finished in 0.002695 seconds.
 
1 tests, 2 assertions, 0 failures, 0 errors

We define a class TestSimpleNumber which inherites from Test::Unit::TestCase. In TestSimpleNumber we define a member function called test_simple. That member function contains a number of simple assertions which exercise my class. When we run that class, we are informed that the 2 assertions are successful.

Python

Assertions are carried out by the assert statement in Python. When it encounters an assert statement, Python evaluates the accompanying expression, which is hopefully true. If the expression is false, Python raises an AssertionError exception, resulting the termination of the program [6].

The syntax for assert is:

assert Expression [“,” Arguments]

in which the Arguments are optional.

We provide a simple example of using assertions in Python.

#!/usr/bin/python

def KelvinToFahrenheit(Temperature):
   assert (Temperature >= 0),"Colder than absolute zero!"
   return ((Temperature-273)*1.8)+32

print KelvinToFahrenheit(273)
print int(KelvinToFahrenheit(505.78))
print KelvinToFahrenheit(-5)

This will produce following result:

32.0
451
Traceback (most recent call last):
  File "test.py", line 9, in <module>
    print KelvinToFahrenheit(-5)
  File "test.py", line 4, in KelvinToFahrenheit
    assert (Temperature >= 0),"Colder than absolute zero!"
AssertionError: Colder than absolute zero!

KelvinToFahrenheit is a function that converts a temperature from Kelvin degrees to Fahrenheit degrees. The function bails out if it sees a negative Kelvin degree.

Eiffel

Eiffel is an O-O language designed for the specification, design implementation and modification of large applications and reusable components. Assertions in Eiffel are used to specify contracts between two objects. The object using an operation of another is called a client while the object providing the operation is the supplier. Unlike other languages, in Eiffel if an Assertion fails, there is a way to handle that situation. In other words the assertions have the capability of handling exceptions which is not present in most of the O-O languages.

Assertions are carried out by the ensure statement in Eiffel [7]. Here is a simple example of using assertions in Eiffel.

class COUNTER
  feature
    count: INTEGER
    increment_by (inc: INTEGER) is
      require
        inc > 0
      do
        -- Implementation goes here
      ensure
        count = old count + inc
    end
end


Summary

We have briefly investigated the use of assertions in various O-O programming language. Assertions, which are Boolean expressions, evaluate to true when the program state satisfies the desired constraints, while evaluate to false meaning that the program has entered into an inconsistent state and hereafter the program behavior cannot be relied upon. Assertions thus provide a powerful tool mechanism for automatic detection of software faults during development, testing and maintenance. They succinctly and unambiguously specify important properties of a program in a way which is easily understandable.


References

  • [1] B. Meyer, Object Oriented Software Construction, Prentice Hall, 1997.
  • [2] C. A. R. Hoare, An Axiomatic Basis for Computer Programming, Communications of the ACM, Vol. 12, No. 10, pp. 576–580,583, October 1969.
  • [3] M. Satpathy, N. T. Siebel and D. Rodriguez, Assertions in Object Oriented Software Maintenance: Analysis and a Case Study, Proceedings of the 20th IEEE International Conference on Software Maintenance, 2004.
  • [4] Programming with Assertions
  • [5] D. Thomas, C. Fowler and A. Hunt, Programming Ruby: The Pragmatic Programmers' Guide (Second Edition), The Pragmatic Programmers, LLC, 2005.
  • [6] Python v2.7 Documentation
  • [7] Eiffel for Beginners