CSC/ECE 517 Fall 2010/ch6 6b AK: Difference between revisions
(20 intermediate revisions by the same user not shown) | |||
Line 34: | Line 34: | ||
*"Postconditions'': Postconditions must be satisfied at exit point of the method | *"Postconditions'': Postconditions must be satisfied at exit point of the method | ||
*''Invariants'': This defines state-space consistency for a class. It is evaluated at the entry and exit point of a class. | *''Invariants'': This defines state-space consistency for a class. It is evaluated at the entry and exit point of a class. | ||
Different languages support assertions at different levels. Following lists and describes these levels briefly: | |||
1. Assertions in design by contract: Assertions can be a part of the documentation. They describe the state of the code before executing a particular statement and the state achieved after executing that statement. They can also specify certain invariants of a class.<br> | |||
2. Assertions for Runtime Checking: Assertions can be used in the actual code implementation to find out if the state of the code is consistent and holds valid values for all the variables taking part in the computations at that point. The main advantage of this approach is that the bug is discovered as soon as it is induced in the system, instead of finding it out later with the help of side effects.<br> | |||
3. Assertions during the development cycle: Normally assertions are enabled during the development cycle by the programmer to find the bugs as quickly as possible. This helps in faster development and less number of bugs later on.<br> | |||
4. Static assertions: Static assertions are performed at compile time and report a more evident kind of bugs which are very easy to spot and fix.<br> | |||
==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 according to the official Python documentation is as follows: | |||
<pre>assert_stmt::="assert" expression ["," expression]</pre> | |||
The second expression is optional | |||
=== Types of Assertions === | |||
==== Runtime Assertions ==== | |||
The example below checks whether a value of a variable is always positive using assertions in Python. | |||
<pre> | |||
x=5 | |||
y=10 | |||
assert x<y </pre> | |||
In the example above, the expression x<y will evaluate to true and therefore, no AssertionError is raised. | |||
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 in xUnit ==== | |||
The standard Unit testing framework in Python is [http://pyunit.sourceforge.net/ PyUnit]. It is a part of the Python standard library. PyUnit is based on the JUnit framework. The pyUnit framework uses the built-in Python ''assert'' statement for assertions. | |||
==Java== | ==Java== | ||
=== Support for assertions === | === Support for assertions === | ||
When Java developed initially it did not have built in support for assertions this is because of very powerful exception handling feature. However Java 1.4 included assertion support. 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. | |||
===Types of assertions=== | ===Types of assertions=== | ||
'''Built in''': Here, support for assertions is directly included in the Java programming language. Java contains language constructs to formulate the assertions. The syntax of assertion command is checked by the compiler and there is a runtime environment in order to check the assertion at the time of execution. This approach helps to integrate assertions into the programming language and the compiler messages are consistent.<br> | |||
'''Preprocessing''': This is the most common approach for the support of assertions. Here the assertions are not placed in the program but are incorporated into the program as comments. There is preprocessor which can interpret the comments and convert the comments into programming code. The advantage of using this approach is to separate the assertion from programming logic. This approach is useful for languages that do not support assertions.<br> | |||
Some examples | |||
<pre> | |||
Assert Value > 10; | |||
Assert CallMethod (); | |||
</pre> | |||
==C++== | ==C++== | ||
===Support for assertions=== | ===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. The assert macro evaluates an expression and prints out a error message to standard error if the expression evaluates to zero. The actual message is dependent on the implementation and varies from compiler to compiler. In most cases, an assertion failure results in the termination of the program using abort. | |||
===Types of assertions=== | ===Types of assertions=== | ||
==== Runtime Assertions ==== | ==== Runtime Assertions ==== | ||
he assert macro can be used for runtime assertions. A simple example is shown below: | |||
<pre> | |||
void print_number(int* myInt) { | |||
assert (myInt!=NULL); | |||
printf ("%d\n",*myInt); | |||
} | |||
=== | int main () | ||
{ | |||
int a=10; | |||
int * b = NULL; | |||
b=&a; | |||
print_number (b); | |||
return 0; | |||
} | |||
</pre> | |||
In this example, assert is used to abort the program execution if print_number is called with a null pointer as attribute | |||
==Ruby== | ==Ruby== | ||
===Support for Assertions=== | ===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 [http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html Official Ruby Documentation] for more information on using the ''Test::Unit'' framework. An assertion failure will result in the exception ''AssertionFailedError'' being thrown with the pertinent information on where the assertion failed which, if required, can be ''rescued'' by the programmer. | |||
===Types of assertions=== | ===Types of assertions=== | ||
====Runtime Assertions ==== | ====Runtime Assertions ==== | ||
The ''Test::Unit::Assertions'' provides a rich set of assertion functions. A simple example is shown below: | |||
<pre> | |||
require "test/unit" | |||
assert_equal 'MY STRING', 'my string'.upcase | |||
</pre> | |||
Other functions include ''assert_match'' for regular expression matching. | |||
<pre> | |||
require "test/unit" | |||
assert (/[a-z]+/, "Match12") # will fail. | |||
</pre> | |||
A complete list of possible runtime assertions can be found at [http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit/Assertions.html RubyDoc]. | |||
==== Assertions during Developmental Cycle ==== | ==== 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.However, since assertions in Ruby are part of the unit testing framework, they are expected to be used only in the test fixture and not in the actual development code. | |||
==== Assertions in xUnit ==== | ==== Assertions in xUnit ==== | ||
Ruby uses the ''Test::Unit'' framework for unit testing and the ''Test::Unit::Assertions'' provides the necessary assertion support. Some of the commonly used assert statements in Ruby are ''assert(), assert_equal(), assert_not_equal(), assert_nil(), assert_not_nil(), assert_same(), assert_not_same()''. | |||
==C#== | |||
== | |||
===Support for assertions=== | ===Support for assertions=== | ||
In C#, you can use the Assert method from either the Debug class or the Trace class (part of the System.Diagnostics namespace). Debug class methods are not included in a Release version of your program, so they do not increase the size or reduce the speed of your release code. C# follows the Design by Contract Approach for implementing assertions. In order to provide assertions in C#, Contract Sharp has been developed which is syntax directed, code development tool with a GUI that helps C# programmers in using assertions in method and class. | |||
===Types of assertions=== | ===Types of assertions=== | ||
'''Debug.Assert Method''': Use the Debug.Assert method freely to test conditions that should hold true if your code is correct. For example, suppose you have written an integer divide function. By the rules of mathematics, the divisor can never be zero. You might test this using an assertion | |||
<pre> | |||
int IntegerDivide ( int dividend , int divisor ) | |||
{ Debug.Assert ( divisor != 0 ); | |||
return ( dividend / divisor ); } | |||
</pre> | |||
When you run this code under the debugger, the assertion statement will be evaluated, but in the Release version, the comparison will not be made, so there is no additional overhead. | |||
== | '''Trace.Assert Method''':Note that calls to the Debug.Assert method disappear when you create a Release version of your code. That means that the call that checks the balance will disappear in the Release version. To solve this problem, you should replace Debug.Assert with Trace.Assert, which does not disappear in the Release version | ||
<pre> | |||
float balance = savingsAccount.Balance; | |||
Trace.Assert ( amount <= balance ); | |||
savingsAccount.Withdraw ( amount ); | |||
</pre> | |||
Calls to Trace.Assert, unlike calls to Debug.Assert, add overhead to your Release version. | |||
Latest revision as of 05:25, 17 November 2010
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
An assertion is a boolean expression that checks the proper state of the program, methods invocation, change in state of data in the class, error handling and the method code for computation. 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
As stated above Assertions are boolean expressions and returns a boolean value, if its false, indicates a bug in the code. It prevents the flow of control to fall into an invalid state which would otherwise can cause serious failures.
/* Defining a object link of type List */
List link;
/* Asserting that the link is not null */
Assert link != null;
In the above example the second statement asserts that link is null. If it is then it throws a AssertionError. In a way, if any line after the assert statement is executed then it can assume that link is not null. In the remaining sections, we compare different OO languages and analyze the support of assertion in the languages.
Usage
- Design by Contract: Assertions may be specified at the class level or on the method level (preconditions and postconditions). A class level assertions, 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 or the entity using the particular 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.
- Development Cycle: During the development cycle, assertions are used as a powerful debugging tool as part of unit testing the code.
- Static assertions: Assertions that are checked at compile time are called static assertions.[1]
Types of assertions in various o-o programming languages
There are different kinds of assertions that can be implemented. A few of them have been listed below.
- Basic assertions: This defines conditions that must be met at a particular line of code.
- Preconditions": Preconditions must be satisfied in order to call a method
- "Postconditions: Postconditions must be satisfied at exit point of the method
- Invariants: This defines state-space consistency for a class. It is evaluated at the entry and exit point of a class.
Different languages support assertions at different levels. Following lists and describes these levels briefly:
1. Assertions in design by contract: Assertions can be a part of the documentation. They describe the state of the code before executing a particular statement and the state achieved after executing that statement. They can also specify certain invariants of a class.
2. Assertions for Runtime Checking: Assertions can be used in the actual code implementation to find out if the state of the code is consistent and holds valid values for all the variables taking part in the computations at that point. The main advantage of this approach is that the bug is discovered as soon as it is induced in the system, instead of finding it out later with the help of side effects.
3. Assertions during the development cycle: Normally assertions are enabled during the development cycle by the programmer to find the bugs as quickly as possible. This helps in faster development and less number of bugs later on.
4. Static assertions: Static assertions are performed at compile time and report a more evident kind of bugs which are very easy to spot and fix.
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 according to the official Python documentation is as follows:
assert_stmt::="assert" expression ["," expression]
The second expression is optional
Types of Assertions
Runtime Assertions
The example below checks whether a value of a variable is always positive using assertions in Python.
x=5 y=10 assert x<y
In the example above, the expression x<y will evaluate to true and therefore, no AssertionError is raised. 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 in xUnit
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. The pyUnit framework uses the built-in Python assert statement for assertions.
Java
Support for assertions
When Java developed initially it did not have built in support for assertions this is because of very powerful exception handling feature. However Java 1.4 included assertion support. 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.
Types of assertions
Built in: Here, support for assertions is directly included in the Java programming language. Java contains language constructs to formulate the assertions. The syntax of assertion command is checked by the compiler and there is a runtime environment in order to check the assertion at the time of execution. This approach helps to integrate assertions into the programming language and the compiler messages are consistent.
Preprocessing: This is the most common approach for the support of assertions. Here the assertions are not placed in the program but are incorporated into the program as comments. There is preprocessor which can interpret the comments and convert the comments into programming code. The advantage of using this approach is to separate the assertion from programming logic. This approach is useful for languages that do not support assertions.
Some examples
Assert Value > 10; Assert CallMethod ();
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. The assert macro evaluates an expression and prints out a error message to standard error if the expression evaluates to zero. The actual message is dependent on the implementation and varies from compiler to compiler. In most cases, an assertion failure results in the termination of the program using abort.
Types of assertions
Runtime Assertions
he assert macro can be used for runtime assertions. A simple example is shown below:
void print_number(int* myInt) { assert (myInt!=NULL); printf ("%d\n",*myInt); } int main () { int a=10; int * b = NULL; b=&a; print_number (b); return 0; }
In this example, assert is used to abort the program execution if print_number is called with a null pointer as attribute
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. An assertion failure will result in the exception AssertionFailedError being thrown with the pertinent information on where the assertion failed which, if required, can be rescued by the programmer.
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" assert_equal 'MY STRING', 'my string'.upcase
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.However, since assertions in Ruby are part of the unit testing framework, they are expected to be used only in the test fixture and not in the actual development code.
Assertions in xUnit
Ruby uses the Test::Unit framework for unit testing and the Test::Unit::Assertions provides the necessary assertion support. Some of the commonly used assert statements in Ruby are assert(), assert_equal(), assert_not_equal(), assert_nil(), assert_not_nil(), assert_same(), assert_not_same().
C#
Support for assertions
In C#, you can use the Assert method from either the Debug class or the Trace class (part of the System.Diagnostics namespace). Debug class methods are not included in a Release version of your program, so they do not increase the size or reduce the speed of your release code. C# follows the Design by Contract Approach for implementing assertions. In order to provide assertions in C#, Contract Sharp has been developed which is syntax directed, code development tool with a GUI that helps C# programmers in using assertions in method and class.
Types of assertions
Debug.Assert Method: Use the Debug.Assert method freely to test conditions that should hold true if your code is correct. For example, suppose you have written an integer divide function. By the rules of mathematics, the divisor can never be zero. You might test this using an assertion
int IntegerDivide ( int dividend , int divisor ) { Debug.Assert ( divisor != 0 ); return ( dividend / divisor ); }
When you run this code under the debugger, the assertion statement will be evaluated, but in the Release version, the comparison will not be made, so there is no additional overhead.
Trace.Assert Method:Note that calls to the Debug.Assert method disappear when you create a Release version of your code. That means that the call that checks the balance will disappear in the Release version. To solve this problem, you should replace Debug.Assert with Trace.Assert, which does not disappear in the Release version
float balance = savingsAccount.Balance; Trace.Assert ( amount <= balance ); savingsAccount.Withdraw ( amount );
Calls to Trace.Assert, unlike calls to Debug.Assert, add overhead to your Release version.
References
- [1] Wikipedia Page Assertions
- [2] Templ J.: Metaprogramming in Oberon, ETH Dissertation No. 10655, Zurich, 1994
- [3] Sun Microsystems: Java Assertion Facility
External Links
- Assertions in Python
- Assert statement in Python
- Unit Testing in Ruby
- Assertions in Ruby
- Design by Contract in Eiffel
- Design by Contract
- More information on Ruby Unit Testing
- Assertions in C++
- JUnit
- Unit testing in C++
- PyUnit.
See Also
- Programming with Assertions
- Design by Contract with Extensible C#
- Test::Unit::Assertions
- Why and How: Ruby (and Rails) Unit Testing
- WHY EIFFEL IS BETTER THAN C++
- xUnit Patterns
==