CSC/ECE 517 Fall 2007/wiki3 1 vb

From Expertiza_Wiki
Jump to navigation Jump to search

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

Sometimes debugging and testing of the code becomes a very tedious task. It becomes difficult to track the problem or able to point out the location of bug in the solution. This is where assertions come into picture. Assertions are Boolean expressions that checks for proper state of the program, method calls for invocation, change in state of data in the class, error handling and the method code for computation.

The syntax of assertion is <assertion_type>(<condition>, <message>); where <assertion_type> indicates what is the assertion made, <condition> indicates a boolean expression that helps to determine whether the assertion is violated or not; <message> will display an error information when the assertion is violated.

Types of Assertions

1) Preconditions: This defines the condition to be satisfied in order to call a method. These conditions are checked at the entry point of method.

2) Postconditions: This defines what the method does. This condition is evaluated at the exit point of the method.

3) Invariants: This defines state-space consistency for a class. It is evaluated at the entry and exit point of a class.

4) Data assertions: This defines conditions that must be met at a particular line of code. These conditions are evaluated at that particular line of code.

Example of Assertion

As stated above Assertion 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.

Following is a simple example of assertion:

/* Defining a object of type TreeNode */

TreeNode root;

/* Asserting that the root is not null */

Assert root != null;

This asserts that root is not 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 root is not null.

In the remaining sections, we compare different OO languages and analyze the support of assertion in the languages.

Integration of Assertion

Assertions support can be put inside the language at many levels. Different languages support assertions at different levels, hence it becomes important to have the knowledge of these levels before delving into the specifics of each language. 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.

Analysis of Support for Assertion in different Programming Languages

Assertions support in Java

It is important to place the assertion statements in the appropriate location for better readibility of the program. In Java, asssetions are placed in the class definition section of the program. Placing the preconditions and postconditions at the start of the class makes them easy to identify. Since precondition is evaluted at the beginning of method call, placing it in the beginning of the class is appropritae but postconditions are treated in a different way. Since they are evaluated at the exit point of method, it must be placed at the top of the method (or before the return statement of the method) and have an assertion tool evaluate the postcondition at all the appropriate conditions. Hence this will improve the readibility of the program. Similarly, invariant is placed in the class definition and evaluated for every entry and exit point of every public method declared in the class. The Java programming language has very little support for assertions but there are different approaches which help to support assertions in java language. They are as follows: a) Built in: Here, support for assertions are directly included in the Java programming language. Java contains language constructs to formulate the assertions. The synatx of assertion command is check by the compiler and there is a runtime environment inorder to check the assertin at the runtime. This approach helps to integrate assertions into the programming language and the compiler messages are consitent, debuggint tools can consider assertions (display stack traces and accuarte line numbers). b) Preprocessing: This is the most common approach for support of assertions. Here the assertions are not placed in the porgram 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 assetion from programming logic. This approach is useful for languages that do not support assertions. The shortcoming of this approach is that original code may be altered and hence the line numbers of compilers do not match with the line numbers of the program. This approach is implemented in Java programming language since it has very little support for assertions.

The iContract Tool for Java programming uses this approach. Programmers add assertion code in the JavaDoc in the form of comments. Then iContract tool translates these comments into assertion code. Another example is Jass (Java with Assertions). The developers write the assertions in Jass and use a preprocessor to translate them into java code.

Integration of Assertion in Java

The assertion is supported in J2SE 1.4. This is supported by adding the keyboard “assert” to the language, and AssertionError class. As mentioned above, assertion is a Boolean expression which must be true during the execution at the runtime. This facility can be enabled and disabled at runtime.
Declaration of Assertion:  Assertion is declared in two forms

assert Expression; assert Expression1  : Expression2; In both of the above forms, the comdition must be true else it will throw an AssertionError at runtime. Some of the examples are as follows: Assert Salary>3000; Assert isStatusEnabled (); Code using assertion: //AssertionDemo.java Class AssertionDemo{ Public static void main(String args[]){ System.out.println( withdrawMoney(1000,500) ); System.out.println( withdrawMoney(1000,2000) ); } public double withdrawMoney(double balance , double amount){ assert balance >= amount; return balance – amount; } } In the above example, the method withdrawMoney is called and the paramters double and amount are passed. The method contains an assertion statement that checks if the balance is greater or equal to the amount. If the condition if false, then AssertionError is thrown.

Assertion support in C #

Assertion checks for conditions that arealways true. Assertions are useful for development and are disabled during runtime. It is useful for testing and debugging. Hence, it helps to main the code in an efficient way. In C#, one can use Assert Method by using either Debug or Trace Class (belongs to System.Diagnostics namespace). 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’s helps C# programmers in using assertions in method and class. C# supports imperative (namespace is System.Diagnostics.Debug) and declarative assertions Imperative Assertion: It is supported using the namespace System.Diagnostic.Debug. If there is an aassertion violation, it thrown an AssertionError dialog. This functionality is completely customizable. Example is shown below:

Declarative Assertions: The assertion is declared in compilation attribute and hence is a part of meta data. It can contain preconditions and postconditons. – RequiresAttribute for pre conditions – EnsuresAttribute for post conditions Declarative assertions are applied for abtract and interface members and are inherited. They need to be enabled at the assembly level. RequiresAttribute: The condition statement is passed to the compilation attribute and then the C# calls the method Debug.Assert(). This can be enabled and disabled at the assembly level.

EnsuresAttribute: Similarly the condition to asset is passed to compilation attribute but it is checked for every return statement of the method. This function call is useful for method with many return statements. The local variable “result” indicates the returned expression

Some of the built-in Assertion attributes: • NotNullAttribute – Expands into “parameter != null” for parameters – Expands into “result != null” for returned values • PositiveAttribute • StrictPositiveAttribute • ValidIndexAttribute – Expands into “entity >= 0 && entity < Count” or “entity >= 0 && entity < Length” or Disadvantages of using Debug.Assert While using Debug.Assert, one must ensure that code inside the Asssert does not affect the results of the program if assert is removed else it might introduce an error when the program is compiled. For example : // unsafe code Debug.Assert (meas(i) != 0 );

If we build the program in release mode, the call to meas is removed and hence counter will not be updated (since meas function increments the counter) Assert Arguments Trace. Assert and Debug.Assert takes up to three arguments. The first argument is mandatory while others are optional. First argument is the condition to be met. Example is below Debug.Assert (stacksize > 0 ); Trace.Assert (stacksize > 0 );

If the assert takes in two or more arguments, one argument is the condition while others are information or messages to be displayed. Example is below:

Debug.Assert ( stacksize > 0, "Out of stack space" ); Trace.Assert ( stacksize > 0, "Out of stack space" );

Below is the code for assertion in C# using System.Diagnostics; class ConfigFile {

   bool isFileOpen;
   public void Open(string strFile) {
       // Pre-conditions
       Debug.Assert(!isFileOpen, "Config file already open.",
           "You can only call Open() once.");
       Debug.Assert(strFile.Length > 0); // check if the length of the    file is more than 0
       isFileOpen = true;
       // ...
   }
   public static void Main() {
       ConfigFile file = new ConfigFile();
       file.Open("Joe.xml");
       file.Open("Joe.xml"); // Causes an assertion!
   }

}

The main function calls the open method which contains the assertion statement. If the condition of the assertion is satisfied (checks if the file contains contents), the file is opened else it will thrown an AssertionError.


Assertion Methods used in Xunit Testing Framework

Assertion Method is a way to obtain an outcome that is executable by computer and useful to user. The outcome of the teat is expressed as a series of assertion statements that specifies the condition that would state the test as passed. These assertions are implemented by calling Assertion Methods which are provided by Test Automation Framwork or by the test automater as Custom Assertions. Assertion reduces the complexity of the conditional test logics by moving the complex code into Test Utility Methods. Hence these methods can be used again and again. All members of Xunity Testing Framework provide Assertion Methods.


Implementation of Assertion

The important features for implemenation are: 1) How to call the Assertion Methods. 2) Which method to call among all the Assertion Methods 3) What information to be displayed in the Assertion Message.

Assertion Methods are named according to how they are accessed. Some of the common variations for accessing Assertion Methods are: a) Assertion Methods are inherited from Testcase Superclass provided by the framework. Hence they are invoked as though that is provided locally on TestCase Class. b) These methods can be provided using globally accessible class or module. They are invoked using class or module name. For eg : Assert.assertTrue(x) c) Assertion methods are provided as mixins or macros. For eg Ruby TestUnit.

Assertion Messages

This is an optional argument in Assertion Methods that provides text message to user when the assertion fails. In Xunit, it is last argument in the list while in Junit, it is the first argument.

Some of the basic Assertion Methods in Xunit Family is below:

1) Single Outcome Assertions: For example : Fail ; It does not take any arguments since it behaves the same all the time.

      Eg: fail( "Expected an exception" );
          unfinishedTest();

2) Stated Outcome Assertions: such as assertNotNull(anObjectReference) and assertTrue(aBooleanExpression); these evaluate a single argument.

       Eg: assertNotNull( a );
           assertTrue( b > c );
           assertNonZero( b );

3) Expected Exception Assertions such as assert_raises( expectedError) { codeToExecute }; these evaluate a block of code and a single expected exception argument.

      Eg: assert_raises( RuntimeError, "Should have raised error")
                 {flight.setMileage(-1122) }

4) Equality Assertions such as assertEqual(expected, actual); these compare two objects or values for equality. Eg: Assert.AreEqual( x, y ); 5) Fuzzy Equality Assertion such as assertEqual(expected, actual, tolerance); these determine whether two values are "close enough" to each other by using a "tolerance" or "comparison mask".

      Eg: assertEquals( expectedXml, actualXml, elementsToCompare );

Example of Assertion Method:

   * Asserts that two objects are equal. If they are not
   * an AssertionFailedError is thrown with the given message.*/
  static public void assertEquals(String message, Object expected, Object actual) {
     if (expected == null && actual == null)
        return;
     if (expected != null && expected.equals(actual))
        return;
     failNotEquals(message, expected, actual);
  }