We will be using Mono in these examples. Mono is an open source implementation of the Microsoft .NET architecture.
Attached to this wiki page is a file named QAExercise.dll. It is a .NET assembly that contains a class named Calculator, which is in the QAExercise namespace.
Calculator has the following methods:
- public int Add(string num1, string num2)
- public int Add(int num1, int num2)
- public int Subtract(int num1, int num2)
- public int Divide(int num1, int num2)
- public int Multiply(int num1, int num2)
- public bool And(int num1, int num2)
- public bool Or(int num1, int num2)
- public string ToHexString(int num1)
There are at least 4 known bugs in this code. Say you are faced with a problem:
Deliver an application that uses the QAExercise.dll assembly. The application should run on the Mono platform, and the application's output should show the Calculator assembly being exercised. The output should have some kind of indication that a bug was found along with where the bug was found and how.
This page contains examples that could help you get started in several languages that can be used with the Mono platform.
We will be using C# in this example.
Unlike Python, which is dynamically typed, C# is statically typed. This means that when the code is compiled, the compiler needs to know the type of each data structure. In this example, the type of each variable is declared explicitly; for example, int result means that the variable result is of the integer type. Prior to C# 3.0, all types must be declared explicitly in this manner.
Beginning with C# 3.0, the language supports anonymous types and type inference. These features are not used in this example, however, C# 3.0 introduces a new "implicit type" called var. This allows the programmer to do something like this:
var foo = 3; var bar = 3.5;
When using the var implicit type, the compiler determines the type of the variable at compile time by determining what type is needed to store the data on the right-hand side of the equals sign. This means that, at compile time, foo will be given the type Int32 (an integer) and bar will be given the type Double.
//filename: calcTest.cs //Import C#'s System namespace. The System //namespace contains the fundamental types of the //runtime, including the Object, Int32, and String //types. using System; //Define your own class class CalcTest { //Define a Main method, where execution will //begin public static void Main (string [] args) { //We know there is a class named Calculator, so //let's instantiate a Calculator object that we can //use to call the Calculator methods QAExercise.Calculator calc = new QAExercise.Calculator (); // The object calc can now be used to call the // Calculator methods //call the public int Add(string num1, string //num2) method int result = calc.Add ("100", "50"); Console.WriteLine ("result: {0}", result); //call the public int Add (int num1, int num2) //method result = calc.Add (100, 50); Console.WriteLine ("result: {0}", result); } }
C# is a compiled language, we compile the code we have written above to a special bytecode called CLI.
Because we are using an assembly that is not part of the Mono libraries, namely QAExercise.dll, we must tell the Mono C# Compiler (mcs) where the assembly is when we compile.
If QAExercise.dll is not in your current/working directory, you must do one of the following before compiling:
Option 1: Add the QAExercise.dll assembly to your Global Assembly Cache by running 'gacutil -i <assembly_path>'
Option 2: Add the assembly path to the MONO_PATH environment variable by running 'export MONO_PATH=<assembly_path>:$MONO_PATH'
Option 3: Use the full path to the assembly with the compiler's "-reference" command-line argument, instead of only using "-reference:QAExercise.dll" like we do below.
Compilation is done like so:
bean@cobweb:~> mcs -reference:QAExercise.dll calcTest.cs
This generates the executable file calcTest.exe. You execute this file like so:
bean@cobweb:~> mono calcTest.exe
Running the file should result in two lines of output. One of the results exposes one of the bugs in the QAExercise assembly.
Unit testing is a procedure used to validate that individual units of source code are working properly.
using System; using Nunit.Framework; class Game { public static void Main (string [] args) { Console.Write ("Try to guess my number: "); string guessTmp = Console.ReadLine (); // type cast to an int int guess = Convert.ToInt32 (guessTmp); try { Assert.AreEqual (answer, guess); } catch (AssertionException) { Console.WriteLine ("Wrong! The answer was {0}", answer); }
To compile this code you will need to include a reference to nunit.framework.dll (in /usr/lib/monodevelop/AddIns/NUnit on openSUSE 10.3).
Before compiling, however, you will need to add nunit.framework.dll to your Global Assembly Cache or MONO_PATH environment variable. Alternatively, you can specify the full path to the dll when compiling. These options are explained in the compiling instructions.
We will be using IronPython in this example. IronPython is an implementation of the Python programming language, targeting .NET and Mono. It allows us to import and use .NET assemblies (e.g., QAExercise.dll).
Python is dynamically typed, so you will notice that you do not need to declare variable types (or even use the var implicit type) like you do in C#.
#filename: calc_test.ipy import sys #To utilize additional .NET libraries, the clr #module must be imported import clr #Add a reference to the QAExercise.dll, #IronPython searches the current/working #directory and its lib directory by default clr.AddReference("QAExercise.dll") import QAExercise #Now we can start using the QAExercise.dll #assembly. class CalcTest: def main(argv = None): #We know there is a class named Calculator, so #let's instantiate a Calculator object that we can #use to call the Calculator methods calc = QAExercise.Calculator() #The object calc can now be used to call the Calculator methods #call the public int Add(string num1, string #num2) method result = calc.Add("100","50") print "result: %s" % result #call the public int Add(int num1, int num2) #method result = calc.Add(100,50) print "result: %s" % result # __name__ is a magic method in Python that can be used to determine # whether the program is being imported from another program if the program # is being run on its own. If __name == '__main__', then we know the # program is being run in its own, so we should act appropriately. In this # case we call the main method in the CalcTest class. if __name__ == '__main__': c = CalcTest(); sys.exit(c.main())
Python is an interpreted language, so it does not need to be compiled. You may simply run the above script like so:
bean@cobweb:~> ipy code/calc/calc_test.py
Running the script should result in two lines of output. One of the results exposes one of the bugs in the QAExercise assembly.
Python (and IronPython) have a built-in assertion statement named 'assert.' Assert statements are a convenient way to insert debugging assertions into a program. The keyboard 'assert' must be followed by an expression (something that will return a value). If the expression returns false, an AssertionError exception will be raised.
Here is an example of a unit test using the assert statement in Python:
answer = 7 guess = raw_input("Try to guess my number: ") guess = int(guess) # type cast string to int try: assert(guess == answer) except AssertionError: print "Wrong! The answer was %d" % answer
In this example, if the user does not enter the number 7, they will see a message telling them they got the answer wrong.
We will be using Boo in this example. Boo is an object-oriented, statically typed programming language for the Common Language Infrastructure. It supports anonymous types, type inference, and duck typing.
Like C#, Boo is statically typed. However, its use of duck typing and type inference make its type system more flexible than C# (even slightly more flexible than C# 3.0 and later). Notice that you are able to use variables without specify a type. You are not even required to use an explicit type like var in C# 3.0 and later. There is also an example of duck typing in the Unit Testing Basics section.
#filename: calc_test.boo import System import QAExercise class CalcTest: def main(): #We know there is a class named Calculator, so #let's instantiate a Calculator object that we can #use to call the Calculator methods calc = QAExercise.Calculator() #The object calc can now be used to call the #Calculator methods #call the public int Add(string num1, string #num2) method result = calc.Add("100","50") print "result: ${result}" #call the public int Add(int num1, int num2) #method result = calc.Add(100,50) print "result: ${result}" # We can define which method the compiler should use as the main entry point # method. This main method can be anywhere in your boo script def Main(argv as (string)): start = CalcTest() start.main()
Boo can be both compiled and interpreted. When a Boo script is compiled, it is transformed into a special bytecode called CLI.
booi is the BOO interpreter. The booi command takes no parameters and the name of the file to be run as its only argument. In other words, to run our sample code as an interpreted script, we do the following:
bean@cobweb:~> booi calc_test.boo
booc is the Boo compiler. Because we are using an assembly that is not part of the Mono libraries, namely QAExercise.dll, we must tell the Boo Compiler where the assembly is when we compile.
If QAExercise.dll is not in your current/working directory, you must do one of the following before compiling:
Option 1: Add the QAExercise.dll assembly to your Global Assembly Cache by running 'gacutil -i <assembly_path>'
Option 2: Add the assembly path to the MONO_PATH environment variable by running 'export MONO_PATH=<assembly_path>:$MONO_PATH'
Option 3: Use the full path to the assembly with the compiler's "-reference" command-line argument, instead of only using "-reference:QAExercise.dll" like we do below.
Compilation is done like so:
bean@cobweb:~> booc -reference:QAExercise.dll calcTest.cs
This generates the executable file calcTest.exe. You execute this file like so:
bean@cobweb:~> mono calcTest.exe
Running the file should result in two lines of output. One of the results exposes one of the bugs in the QAExercise assembly.
Boo has a built-in assertion statement named 'assert.' Assert statements are a convenient way to insert debugging assertions into a program. The keyboard 'assert' must be followed by an expression (something that will return a value). If the expression returns false, an AssertionError exception will be raised.
Notice that, in Boo, you are able to use variables without specifying a type (type inference, e.g., line 1) and assign two different types do the same variable (duck typing, e.g., guess is a string on line 2 and an int on line 3).
Here is an example of a unit test using the assert statement in Boo:
answer = 7 guess = raw_input("Try to guess my number: ") guess = int(guess) # type cast string to int try: assert(guess == answer) except AssertionError: print "Wrong! The answer was %d" % answer
In this example, if the user does not enter the number 7, they will see a message telling them they got the answer wrong.






Whoever thinks Pythons syntax is a good thing to duplicate is brain dead and does not know anything about language design!