CSC/ECE 517 Fall 2007/wiki3 1 sa

From Expertiza_Wiki
Jump to navigation Jump to search

Support for assertions in various o-o programming languages

Topic :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

"In computer programming, an assertion is a predicate (i.e., a true–false statement) placed in a program to indicate that the developer thinks that the predicate is always true at that place. Assertions are used to help specify programs and to reason about program correctness. For example, a precondition — an assertion placed at the beginning of a section of code — determines the set of states under which the code is expected to be executed. A postcondition — placed at the end — describes the expected state at the end of execution. "[1]

Assertions are essentially a way to implement testing in computer programming and are specified by the programmer to check for correctness in a program. Assertions are a systematic way to check that the internal state of a program is as the programmer expected, with the goal of catching bugs. In particular, they are good for catching false assumptions that were made while writing the code.

Example

Following is a very simple example of an assertion in Java.

if (i % 4 == 0) {
       ...
   } else if (i % 4 == 1) {
       ...
   } else if (i % 4 == 2) {
       ...
   } else {
       assert i % 4 == 3 : i;
       ...
   }

In the above example we know that if the first three conditions are false then i % 4 has to evaluate to 3 and this is asserted using assert. Note that even in this case the assertion may fail if i is negative.

Usage

  • Design by Contract: Assertions may be specified at the class level (invariants) or on the method level (preconditions and postconditions). An invariant is a correctness condition imposed on a class, i.e., a condition that must not be violated by any method of a class. A precondition is associated with a particular method and imposes a correctness condition on the client of the method: i.e., the client must ensure that the precondition is fulfilled; otherwise the method is not executed. A postcondition is also associated with a particular method, but it imposes a correctness condition on the implementation of the method; a violation of a postcondition indicates an error in the implementation of the method.
  • Runtime checking: Assertions that are a part of the implementation and can be checked at run time for correctness. This is a very common usage of assertions.
  • Development Cycle: During the development cycle, assertions are used as a powerful debugging tool. The point at which the assertion failure occurs teh programmer is immediately notified so that he can go ahead and fix the bug.
  • Static assertions: Assertions that are checked at compile time are called static assertions.[1]

Support for assertions in various o-o programming languages

Depending on the programming language, assertions can either be a part of the design process or they could be statements which are checked at runtime. In this page we are trying to research the support for assertions present in various o-o programming languages. The research is based on two main criteria:

1. How well the support for assertions is integrated with the language

There are several ways in which assertions are supported in different languages. Listed below are few strategies for providing this support.

  • Built-in support: This means that support is directly included in the programming language. The programming language contains language constructs to formulate assertions in one way or another. The syntactical correctness of assertions is checked directly by the compiler. In addition a runtime environment must be available to perform the runtime assertion checks and also should be able to selectively enable and disable assertion checking.
  • Preprocessing: The general idea here is to formulate assertions separate from the program or to include the assertions as comments. A preprocessor is used to weave the assertions into the program or to transform the comments containing assertion formulas into programming language code. The main advantage of this approach is the separation of programming logic and contracts. This is important in cases, where the programming language itself does not support assertions and the programming language must not be altered. The main disadvantage of this approach is that the original program code is changed by the preprocessor, i.e., line numbers of compiler errors do not actually fit the line numbers of the program. The same problem arises with debugging or runtime exceptions.
  • Metaprogramming: According to Templ metaprogramming refers to “programming at the level of program interpretation, or in other words, to extending the interpreter of a given programming language in an application-specific way. Traditionally, this concept is available only in dynamically typed and interpreted languages” [2].

2. How many different kinds of assertions the language supports

There are different kinds of assertions that can be implemented. A few of them have been listed below.

  • Basic assertions: Annotations in the implementation of a method.
  • Preconditions and Postconditions
  • Invariants

Java

Support for assertions

Java, when developed initially, did not have any built-in support for assertions. This was probably because it's exception handling feature was very powerful. However the (beta) release 1.4 of Java 2 included a built-in assertion facility. An assertion is a statement in the JavaTM programming language that enables you to test your assumptions about your program. Java Assertion Facility is a built in kind of support since Java 1.4 release. Java supports a very simple assertion mechanism that allows to formulate correctness conditions within methods. Assertion checking can be easily enabled and disabled and traces of assertions may be eliminated completely from class files. [3]

Types of assertions

Java supports runtime assertions since it is a statically typed language. It also allows specifying the pre-condition and post-condition, internal invariant type of assertions.

A very simple switch-case example can be formulated as follows where an assertion is used for the default case.

switch(color) {
     case Color.RED:
       ...
       break;
     case Color.YELLOW:
       ...
       break;
     case Color.BLUE:
       ...
       break;
     case Color.GREEN:
       ...
     default:
       assert false : suit; 
   }

C++

Support for assertions

There is no native support for assertions in C++. Assertions are, however, part of the standard library header assert.h which defines the macro assert.

Types of assertions

Runtime Assertions

The assert macro can be used for runtime assertions. A simple example is shown below:

 #include<assert.h>

 int main()
 {
   int x=3;
   int y=4;

   assert((x-y)>0); //false. Will terminate the program.
 }

An assertion failure will usually result in the termination of the program.

Assertions during Developmental Cycles

The assert macro is defined only if NDEBUG is not defined. Therefore, a programmer can define 'NDEBUG' using a #define NDEBUG during the release cycle to remove all assertions in the code. There is no performance penalty in this case.

Assertions in Design by Contract

Assertions in Design by Contract are supported in C++ using third party tools such as the DBC for C preprocessor, GNU Nana, C², or the Digital Mars C++ compiler.

Ruby

Support for Assertions

Ruby does not have native support for assertions. Assertions are supported using the Test::Unit framework. Test::Unit::Assertions contain the standard Test::Unit assertions. Please refer to the Official Ruby Documentation for more information on using the Test::Unit framework.

Types of assertions

Runtime Assertions

The Test::Unit::Assertions provides a rich set of assertion functions. A simple example is shown below:

require "test/unit"

x=8
assert x>0 # will return true
assert_equal(x,7,"Equality test failed!") # False. Test will fail.
 

Other functions include assert_match for regular expression matching.

require "test/unit"
   
assert (/[a-z]+/, "Match12") # will fail.

A complete list of possible runtime assertions can be found at RubyDoc.

Assertions during Developmental Cycle

Since, Ruby does not have native support for assertions there is no way to turn off assertions during runtime unless the programmer explicitly does so.

Assertions in Design by Contract

Ruby support assertions in Design by Contract using third party libraries like Brian McCallister's DesignByContract, Ruby DBC or ruby-contract.

Python

Support for Assertions

Assertions in Python are built into the language and are implemented using the assert statement. The syntax for the assert statement is as follows:

assert_stmt::="assert" expression ["," expression]

The second expression is optional. Please refer to Python Documentation for more information on the assert statement syntax.

Types of Assertions

Runtime Assertions

The example below checks whether a value of a variable is always positive using assertions in Python.

x=5
assert x>0 #will be true as long as x>0

An AssertionError is raised whenever an assertions fails and usually terminates the program.

The assert statement can also be used for type checking since python is a dynamically typed language. This is useful in making sure the type of the arguments to an function are correct.

from types import *

def foo(x,name)
 assert type(x) is IntType, "id is not an integer: %s" % `id`
 assert type(name) is StringType, "name is not String: %s" % `name`

The string expression at the end of the assert statement is printed out only if the assertion fails.

Assertions during Developmental Cycle

Assertions in python are executed only in debug mode and can be disabled by passing the "-O" option to the python interpreter. This allows the developer to turn off assertions in the release builds to avoid unnecessary performance slowdowns.

Assertions in Design by Contract

Python does not have native support for assertions in Design by Contract(DBC). However, there are third party libraries like PyDBC or Contracts for Python which add support for DBC.

Eiffel

Support for assertions

Eiffel has native support for assertions through Design by Contract.

Types of assertions

Design by Contract

Eiffel supports assertions only through Design by Contract. Eiffel uses the require statement to indicate pre-conditions and ensure statement for post-conditions. The example[1] below illustrates this using a simple dictionary insertion function.

put (x: ELEMENT; key: STRING) is
                     -- Insert x so that it will be retrievable through key.
             require
                     count <= capacity
                     not key.empty
             do
                     ... Some insertion algorithm ...
             ensure
                     has (x)
                     item (key) = x
                     count = old count + 1
             end

xUnit testing frameworks and assertions

Different programming languages support Unit testing using frameworks specific to that language. In this section we briefly discuss for some o-o programming languages.

  • Java

Java uses the JUnit testing framework. Here the assert functions are responsible for all the testing. Different assertion functions can be included in the code to run the required tests. Detailed dcoumentation is available in the official website for JUnit.

  • C++

In C++, there is no one standardized framework but it does have several testing frameworks with different APIs. A list of these can be found here.

  • Ruby

In Ruby there is no native support for assertions. This feature is implemented using in the Test::Unit framework

  • Python

The standard Unit testing framework in Python is PyUnit. It is a part of the Python standard library. PyUnit is based on the JUnit framework.

References

External Links

See Also