View Ravichandran J.V.'s profile on LinkedIn Ravichandran J.V.'s Blog Tweet @ravichandranjv

Translate

Thursday, 25 April 2013

My Personal Ledger - Work on the move

Work on the move, upload to cloud, sync up with your workstation or client. Sounds good?


Wednesday, 24 April 2013

GREYcells Ludo

Upcoming app - Ludo for Android

Tuesday, 9 April 2013

EasySudoku

Look for it on Google Store in a week's time!
 


Monday, 25 March 2013

Easy Sudoku - Alpha version 1

Easy Sudoku - Alpha Version 1
 
 
(Representation image).
Currently testing that all numbers can be moved around...
 

Thursday, 21 March 2013

Know your India - Android app


The graphics need to be polished for production and the map, too. :)

Tuesday, 26 February 2013

"The Train" design pattern

If design patterns have emerged or are supposed to emerge from pattern-mining, many of the design patterns, if not all, are like over-worked donkeys and consuming resources like an Elephant in a middle-class family.

Design patterns, in the current, technologically well-established and stable world, needs to be able to enhance its own effectiveness by regrouping itself to make use of available resources.

Design patterns have been regarded as solutions to similar problems with a total disregard to how platform changes, resource managemrnt improvements, hardware improvements, hardware-software collaboration may affect the outcome of a designed solution.

The modern, post-web 2 world of design patterns has to be inherently dynamic enough to accomodate even language enhancements to utilize, optimally, hardware advancements like parallel processing or greater memory addressing powers.

"The Train" pattern that I am talking about here will not only be the basis for all modern artifacts like a computer game, it may also serve as the right solution to serve dynamically changing artifacts in processes.

The model of this pattern is already posted on this blog as a procces model.

I will post this pattern in an Android app, first, and later as the controller of a game.

Monday, 18 February 2013

Working software

If a software works and gives the desired result, that is the first successful step in software development.

Refactoring, UI design, 'code smell', object/class design, whether to use a lst or a collection or a dictionary of objects and all the other fancy stuff that are dished out, by the dozen, in training and coaching sessions, do not matter if the software is not working.

Neither does 'working software' or 'software', in this context, means the complete software with all the features. It just means that you have created the 'sufficient' code that is 'stable' and provides a solid base to achieve the requirements set.

Saturday, 16 February 2013

Multiple linear layouts

Layout 2 on top belongs to 'Layout 1'
 

 

Tuesday, 12 February 2013

ReArrange on the Android tablet

 ReArrange - Signed, uploaded, installed on the Android. :)

If you have an Android device, please do email me and I will mail you the .apk file.

Not yet uploaded to Google Playstore...

Thursday, 7 February 2013

The XO 3 - what the child in India wants

The OLPC laptop (XO as it is called) (images are the Concept design)

is a dream for any nation's child education plans and especially for India because of its robustness (unbreakable body), battery that can be charged from solar energy and even through a hand-crank tool and more importantly, it is designed by educationists and targets the education sector making it customizable for any educational requirement with a full-fledged localization projects on different Indian languages.
 
 

"Designed by Yves Behar's Fuseproject, the XO-3's new design features an all plastic tablet screen which is semi-flexible and extremely durable, and just like the original XO, the display can be optimized in both transmissive and reflective modes for indoor and outdoor lighting conditions.

The XO-3 supports many use scenarios to fulfill kids’ learning needs: from horizontal book mode to portrait reading mode to multi-touch--so many hands can play and learn together on the same screen--to a full-touch keyboard and a back facing camera. " onelaptop.org

Existing features (reliable list because I have an XO) - Wi-fi, 3G capability, audio-video, touch screen, open source code, a huge community of Indian techies and a galore of other goodies.

Cost ? Immaterial as OLPC India also provides for an option that is successful in the UK and even the World Bank subscribes - a lending library.

 

At Amity University, Noida

Delivered a talk on "Agile", mindset management etc to Amity university in Noida on the 24th January, 2013.

 

Wednesday, 6 February 2013

TicTacToe Simplified - Android game

The UI update, in this basic example, done in the onClick method should be done in a separate thread (in the adapter or any middle layer). I

f you are doing an Android project at school or university, this is the simplest and quickest solution for you.



 
 
 

@TargetApi(Build.VERSION_CODES.HONEYCOMB)

@Override

public void onClick(View v) {


if (gameOver==false){




ImageCell c=(ImageCell)v;

if (playerId==1){




c.

cells[c.cellNumber]=1;

gameOver=c.isWinner(c.cellNumber);




c.setImageResource(R.drawable.

x);




c.setScaleType(ScaleType.

FIT_XY);




}

if (playerId==2){




c.

cells[c.cellNumber]=2;




c.setImageResource(R.drawable.

o_tic);




c.setScaleType(ScaleType.

FIT_XY);

gameOver=c.isWinner(c.cellNumber);




}

playerId++;


if (playerId>2)playerId=1; 

moveCount++;




Toast.makeText(v.getContext(),

"Player "+ playerId +", your turn !",Toast.LENGTH_SHORT).show();




}

if (gameOver==true || moveCount>=9){




Toast.makeText(v.getContext(),

"Game over!",Toast.LENGTH_SHORT).show();

gameOver=true;




finish();
}

Get image clicked in a grid - Android



I have titled these Android related posts to match Google searches as the many results I found on the web are pretty complicated.

Here is the simple way using the AdapterView. Extend your class with BaseAdapter that gives you a getView() method to implement your view in a Grid.


// The main activity class

import android.os.Build;
import android.os.Bundle;
import android.annotation.TargetApi;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.Toast;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class MainActivity extends Activity implements OnClickListener {
 ImageView v,v1;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  GridView gv=(GridView) findViewById(R.id.image_grid_view);
  gv.setAdapter(new ImageCellAdapter(this));
       }
  @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 @Override
 public void onClick(View v) {
  String msg=" " + v.getId();
  Toast.makeText(this, "Clicked "+msg,Toast.LENGTH_SHORT).show();
 }
// The adapter class

import android.content.Context;
import android.text.Layout;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.*;
public class ImageCellAdapter extends BaseAdapter
{
public static final int DEFAULT_NUM_IMAGES = 8;
public ViewGroup mParentView = null;
private Context mContext;
public ImageCellAdapter(Context c)
{
    mContext = c;
}
public int getCount()
{
    return mThumbIds.length;
}
public Object getItem(int position)
{
    return mThumbIds[position];
}
public long getItemId(int position) {
    return position;
}
public View getView (int position, View convertView, ViewGroup parent)
{
    mParentView = parent;

    ImageCell v = null;
    if (convertView == null) {
        v = new ImageCell (mContext);       
    } else {
        v = (ImageCell) convertView;
    }
    v.setImageResource (mThumbIds[position]);
    v.cellNumber = position;
    v.setId(position);
   //v.setLayoutParams(LayoutParams.WRAP_CONTENT));
    v.setOnClickListener ((View.OnClickListener) mContext);
    return v;
}
public Integer[] mThumbIds = {
  R.drawable.ic_launcher, R.drawable.re,
        R.drawable.r12, R.drawable.t12,
        R.drawable.b12, R.drawable.k12,
        R.drawable.f12, R.drawable.l12,
        R.drawable.o12, R.drawable.m12,
        R.drawable.p12, R.drawable.s12,
        R.drawable.c12, R.drawable.a12,
        R.drawable.h12, R.drawable.e12,
        R.drawable.g12, R.drawable.d12,
        R.drawable.i12, R.drawable.w12,
        R.drawable.n12, R.drawable.y12,
        R.drawable.z12, R.drawable.u12,
        R.drawable.q12, R.drawable.v12,
        R.drawable.j12, R.drawable.x12,
        };
}
// The image cell class

public class ImageCell extends ImageView
//implements OnClickListener
{
//    public boolean cellEmpty = true;
    public int cellNumber = -1;
  //  public GridView gv;
public ImageCell (Context context) {
 super (context);
}
public ImageCell (Context context, AttributeSet attrs) {
 super (context, attrs);
}
public ImageCell (Context context, AttributeSet attrs, int style) {
 super (context, attrs, style);
}
}
// The activity XML


<

LinearLayout xmlns:android=http://schemas.android.com/apk/res/android

android:layout_width="fill_parent"

android:layout_height="fill_parent" 

>

 

<GridView xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/image_grid_view"

android:layout_width="fill_parent"
android:layout_height="fill_parent"

android:numColumns="9"

/>

 

</LinearLayout>

Get Id of Image clicked in a layout

A simple example of handling a click event on an image in a linear layout. You will need three images in your res/drawable folder of the Android app.

The main activity XML that defines the layout structure and the image view(s).

//mainactivity.xml

<
LinearLayout xmlns:"http://schemas.android.com/apk/res/android

        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
            android:id="@+id/lView1"       
        >   
< ImageView
                    android:id="@+id/imageView1"            
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/re"
            android:tag="0"
            />

<ImageView
                    android:id="@+id/imageView2"            
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher"
            android:tag="1"           
            />

<ImageView
                    android:id="@+id/imageView3"            
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/m12"
            android:tag="2"
            android:onClick="onClick"           
            />
        </LinearLayout>



and the corresponding .java class. Note that the clickhandler is in code as well as in the xml file.
 
// MainActivity.java

import android.os.Build;
import android.os.Bundle;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipDescription;
import android.view.DragEvent;
import android.view.Menu;
import android.view.View;
import android.view.View.DragShadowBuilder;
import android.view.View.OnClickListener;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener,OnDragListener,OnLongClickListener {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
        LinearLayout l = (LinearLayout) findViewById(R.id.lView1);    
        if (l == null) Toast.makeText(this, "Unable to find GridView",Toast.LENGTH_SHORT).show();
        else {
       
            ImageView v = (ImageView) l.findViewById(R.id.imageView1);
            ImageView v1 = (ImageView) l.findViewById(R.id.imageView2);
            v.setOnClickListener ((View.OnClickListener) this);
            v1.setOnClickListener ((View.OnClickListener) this);
            v.setOnLongClickListener((View.OnLongClickListener) this);
            v1.setOnLongClickListener((View.OnLongClickListener) this);
        }

 }
 public Integer[] mThumbIds = {
         R.drawable.ic_launcher, R.drawable.m12,         
 };
 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  // Inflate the menu; this adds items to the action bar if it is present.
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 @Override
 public void onClick(View v) {
  String msg=(String) v.getTag();
  Toast.makeText(this, "Clicked "+msg,Toast.LENGTH_SHORT).show();
 }
 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 @Override
 public boolean onDrag(View v, DragEvent dragEv) {
  // TODO Auto-generated method stub
  return false;
 }

Tuesday, 22 January 2013

Android JUnit test

It is really funny how you can do functional testing with the Android Junit Test by extending the ActivityInstrumentationTestCase2 !

Is it a better "jugaad" than Indian "jugaads" ?

Looks so because the JUnit 4 Test Runner simply does not work without extending the ActivityInstrumentationTestCase2 (no need to extend it but just to see what the message is) but returns a ClassNotFoundException !


 

Thursday, 17 January 2013

Sunday, 30 December 2012

Story boards

Story boards are extensively recommended for use in an Agile team but where was this idea used first?

Email your answers to me. It will be fun to interact! :)

Tuesday, 25 December 2012

Removed malware

When I updated my blog with program code from another decade, Blogger complained of malware. Removed all link references from earlier blog that was embedded in the program codes.

Friday, 21 December 2012

20 years + in software development ! ;P

Realized that I started coding/developing software two decades ago. Still remember every line of code. Posted on the side bar and the bottom of the blog.

Friday, 30 November 2012

At Patna for the OLPC Demo - 27th - 29th Nov 2012

Demo of the OLPC Laptop



Leadership Training on the Use of ICT in Teacher Education in Bihar: Strategic Workshop



Demo of the OLPC laptop 


Wednesday, 14 November 2012

BDD with NBehave starter example

Here is a quick help for BDD with NBehave beginners.

Also refer to this presentation by me on BDD and UADD at the Agile NCR conference  - BDD and UADD with Slim

The .feature text  file that describes the scenario(s) and which gets executed by NBehave !


The ActionSteps that define the actions proposed in the .feature file above in the BDD format of Given, When, Then.


And the production class,

 public class Calculator
    {
        private int result;
        private int one, two;
        public void Enter(int o,int t)
        {
            one = o;
            two = t;
        }
        
        public void Add()
        {
            result = one + two;
        }
        public int Value() {
           return result; 
        }
    }

Below is the nbehave results



Monday, 12 November 2012

Behavior Driven Development with Tumbler

Will elaborate on comments and questions to this post :)

More on this can be found at - http://ravichandranjv.blogspot.in/2010/05/decision-table-in-slim.html

Also refer to this presentation by me on BDD and UADD at the Agile NCR conference  - http://tinyurl.com/d6xjfox


import static tumbler.Tumbler.*;

import org.junit.runner.Result;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
import tumbler.Scenario;
import tumbler.Story;
import org.hamcrest.BaseMatcher;
import org.hamcrest.core.IsEqual;
import org.hamcrest.core.IsNot;
import org.hamcrest.core.IsNull;
import org.hamcrest.core.IsSame;
import tumbler.JUnit44TumblerRunner;
import tumbler.TumblerRunner;

@RunWith(JUnit44TumblerRunner.class)
@Story("Generate genome sequence from values passed")
public class GenomeTest {
@Scenario("ATGAC")
    public void shouldGenerateCorrectPatern() {
        Given("A Genome sequence");
        GenomePattern gp = new GenomePattern();
        Object someValue=null;

        When("Genome pattern is to be generated");
        Result result = gp.generatePattern();

        Then("expect ATGAC");
        assertNull(result); // Making test pass as per TDD
    }
}

Sunday, 11 November 2012

Parameterized test with HashMap example - JUnit


A rather contrived example but since there is a dearth of JUnit example on parametrized tests on the web it should help plus JUnit parameters is itself a little contrived ! :) Theories and Datapoints are a better option...will post soon on Theories.

package parameterTests;

import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(value=Parameterized.class)
public class ParameterAnnotation {
private Map geo;
      @Parameters
public static Collection configs() { Map geo1 = new HashMap(); geo1.put("Country", "India"); geo1.put("Capital", "New Delhi"); return Arrays.asList(new Object[][] { { geo1 } }); }      public ParameterAnnotation(Map geo) {
        this.geo = geo;
    }

 @Test
public void pushTest1() {
    assertEquals("India", geo.get("Country"));
    assertEquals("New Delhi", geo.get("Capital"));
}
}

Parameterized test example - JUnit


import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.List;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

@RunWith(value=Parameterized.class)
public class ParameterAnnotation {
private int number;
public ParameterAnnotation(int number) {
   this.number = number;
}
private static int currentIndex, nextIndex;
@BeforeClass
public static void initClassValues(){
currentIndex=0;
nextIndex=0;
}
private static Object[][] data=new Object[5][1];

@Parameters
public static List data() {
       data[0][0]=1;
       data[1][0]=2;
       data[2][0]=3;
       data[3][0]=4;
       data[4][0]=5;
       return Arrays.asList(data);
}
@Test
public void pushTest() {
assertEquals(number, data[currentIndex][nextIndex]);
currentIndex++;
}
}

Friday, 9 November 2012

JUnit and MockItTo test (Arrange, Act, Assert & Verify)

A simple scenario of an assert and a setting expectation with MockItTo:


1. @Test
2. public void call_should_return_hello_world(){
// Arrange
3. HelloWorld h=mock(HelloWorld.class);
// Act
4. when(h.sayHello()).thenReturn("Hello World");
// Assert
5. assertEquals("Hello world", h.sayHello());
// Verify
6. verify(h).sayHello();
}

Line 4 sets the expectation (a la BDD style), that when sayHello() is called the value returned should be the string passed to thenReturn.

Line 5 performs an assertion, totally independent of the mock expectation set.

Line 6 verifies that the method call was made on the mock object "h", at least once, the default.

So, what does this example serve for? It helps as an example to differentiate between the expectation of a JUnit assert from a mock expectation regardless of the type of object on which the method call is made.

Comment Line 5 and Line 6 will fail with

"Wanted but not invoked:
helloWorld.sayHello();
-> at Hello_Mockito.call_should_return_hello_world(Hello_Mockito.java:34)
Actually, there were zero interactions with this mock.

Simplify the code with annotations:


@RunWith(MockitoJUnitRunner.class)
public class Hello_Mockito {
// Arrange
@Mock
HelloWorld h;
@Test
public void call_should_return_hello_world(){
//HelloWorld h=mock(HelloWorld.class);
                        // Act
when(h.sayHello()).thenReturn("Hello World");
                       // Assert
assertEquals("Hello World", h.sayHello());
           // Verify
                       verify(h).sayHello();
}
}

Monday, 15 October 2012

Sudoku puzzle and solution unit test

Using "async" and "await" and NUnit 2.6.2's new async support, I have embarked on the fascinating task of creating a Sudoku set of solutions.

This is the first step - to get the basic logic right, based on whatever type of input (in this context, it is a random selection of values), to achieve a working solution. Lots of re-factoring to the domain methods to follow with asynchronous events adding to the beauty of the solution! Rerun the IsSolutionGenerated test in a loop (with, if necessary, tweaks) and you will get the complete solution (though, mind yourself, not the complete game).

Many would want to use a Main() or a print values method but that is the tendency that you have to curb, if you wish to get into TDD. Why do you want to "see" the results when you do not know if the code is behaving properly? If at all you want to see the output, use the Console.Write...method(s) in your unit tests and view it in the Text Output tab of the NUnit GUI.

To start off, here is a unit test class for a single set of 9 unique values solution. The domain class can be accessed here


   [TestFixture]
    public class SudokuGridTests
    {
        SudokuGrid ob = new SudokuGrid();
        [SetUp]
        public void InitializeGame()
        {

        }
        [Test]
        public void CheckIfGridEmpty()
        {
            ob.StartGame();
            Assert.True(ob.IsGridEmpty());
        }
        [Test]
        public async void IsSolutionGenerated()
        {
            Assert.True(await ob.GenerateSolution());
        }
    }

Friday, 12 October 2012

Agile series V - TDD, UADD and BDD, briefly

Briefly put, in TDD, you write a test first, if the test fails, write only that much code to make it pass and if the test passes, write another test. The goal is to write a new unit test once the previous test has passed. Let the design evolve from this sequence.

Once the code is stable, brush it up with some re-factoring and showcase it (or present it) to  the tester for user acceptance tests. If the tester comes up with bugs or with exceptions, go back to the previous step of writing more unit tests to be able to determine what code should be written for the user acceptance to happen!

In UADD, start backwards. Get the UAC and then start your TDD ! Simple !

BDD is just a step further ! :)

http://ravichandranjv.blogspot.in/2012/11/bdd-with-nbehave-starter-example.html
http://ravichandranjv.blogspot.in/2012/11/behavior-driven-development-with-tumbler.html

Happy TDD & UADD !

Agile series IV - after refactor!

The method "Subtract" (It was "Substract" initially. In this snapshot, you see a red double dash under the "t" because I had corrected the spelling but not rebuilt it!) was not called because of misspelling and the resulting coverage is below!


Added try-catch and refactored all the return statements into individual statements


After full refactor..




Agile series III - UAT with Slim/Fitnesse

Failing tests because user input is also negative! Wrong expectations ?


3 Failing tests and 2 exceptions! Wrong expectations or wrong code?


Thursday, 11 October 2012

Agile series II - The not-so-perfect world!

The previous post is all about how perfect the software world is, given perfect behaviour of code! But, nothing in our knowledgeable world is perfect because that is the reason everything, in our known world, constantly evolves or "changes".

And so, we will start with the "assumption" that our code is perfect and start giving it all kinds of "whacky" inputs! Whacky means that we do everything that goes against the expectations of the "perfect" code but with the goal of achieving 100 % code coverage ! For instance, we will provide a combination of negative and positive and zero values to the domain class and see how it behaves! Simple !

And this is what the user, who did not create the code and therefore, does not know. So, here ends unit testing and  begins User Acceptance Testing where we supply the code with all kinds of inputs and the entity that will do it should be some entity that did not write the code - it could be the end user, the customer, the tester or just about anybody.

If there is a user interface, we could use the input mode to take the input; if not, we supply it through an automated testing tool like Fitnesse!

And from here starts testing for exceptions, wrong inputs and unformatted inputs.

The passing UAT test with FitNesse/Slim framework is below


This is the fitnesse way of doing it! Write a separate fixture class and test it with two public fields, firstValue and secondValue, and have different methods for testing. That is, just to do UAT you need a separate Fixture class written by the dev.

The Slim way is straightforward. Just consume the same domain class for UAT!

Below is the Slim script for the same class that had been unit tested and for which the code coverage was 100 %.



Contd...in subsequent posts.

A simple coverage example - NCover 4 - Agile series I

The failing test, TestMultiply, decreases the coverage % plus the two methods, Subtract and Divide, do not have unit tests, which also decreases the coverage. 


    [TestFixture]
    class TestCoverage_Class2
    {
        Coverage_Class1 initCoverage = new Coverage_Class1(55, 12);
        [Test]
        public void TestAdd()
        {
            Assert.AreEqual(67,initCoverage.Add());
        }
        [Test]
        public void TestMultiply()
        {
            Assert.AreEqual(60, initCoverage.Multiply());
        }
    }

// Domain class being tested

public class Coverage_Class1
    {
        int firstValue, secondValue;
        public Coverage_Class1(int a, int b)
        {
            firstValue = a;
            secondValue = b;
        }
        public int Add()
        {
            return firstValue + secondValue;
        }
        public int Multiply()
        {
            return firstValue * secondValue;
        }
        public int Subtract()
        {
            return firstValue - secondValue;
        }
        public int Divide()
        {
            return firstValue / secondValue;
        }
    }

Write the two tests for the additional two methods, Divide and Subtract, with one of them a failing test and the coverage looks like this:



Make them all pass and voila, 100 % coverage  !




Work around with the Threshhold values and you will increase your own coverage capabilities ! :) Happy Coverage! :)


Wednesday, 10 October 2012

New in NCover - Change Risk Analysis & Predictions (CRAP)

This coverage report for the previous post

Max Crap Score - 6 (Max. - 930 calculable of 999)



Max complexity


Saturday, 6 October 2012

Thread.Sleep is not the same as await

Note: Since Blogger eats up less than and greater than symbols, please replace async Task with Task of int as in generic types.

The most common mistake that many make about asynchronous processing is to think that Thread.Sleep means asynchronous. To demonstrate this is the below code, which is a "buggy" code because of the Thread.Sleep call.


// The code

using System.Threading.Tasks;

namespace Net45.UnitTests.Samples.Jv
{
    public class ClassUnderTest
    {
        public static int? taskId;
        public static string taskName;
        public static int result;
        public async Task "less than" int "greater than" AddWithTask(int a, int b)
        {
            await Task.Factory.StartNew(async () =>
            {
                taskName = "AddWithTask";
                taskId = Task.CurrentId;
                result = await add(a, b);
            });
            return result;
        }
        public async Task "less than" int "greater than"add(int a, int b)
        {
            int x = 0;
             Task.Factory.StartNew( ()=>            
            {
            x = a + b;
            taskId = Task.CurrentId;
            System.Threading.Thread.Sleep(20); // Without using this statement you will see the tests failing (as shown in point 5 in the previous post), the synchronous task continues its execution giving the impression that using Thread.Sleep() makes for asynchronous processing (because if you use the  code without a test, the code will compile and execute correctly but not with the expected result), Await makes the caller receive the callback result and not Thread.Sleep. 
To see it in action, modify the async method above to look like this
public async Task 
"less than" int "greater than" add(int a, int b)
        {
            int x = 0;
            await Task.Factory.StartNew( ()=>            
            {
            x = a + b;
            taskId = Task.CurrentId;
            //System.Threading.Thread.Sleep(20);
            });
            return x;
        }

            });
            return x;
        }
        public async Task "less than" int "greater than"returnAdditionResult(int a, int b)
        {
            int x = 0;
            x = await add(a, b);
            return a+b;
        }

    }
}


// The test class

using System;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
namespace Net45.UnitTests.Samples.Jv
{
    [TestFixture]
    public class AnthonySteeleClass
    {
        ClassUnderTest cutHandle = new ClassUnderTest();
        int? taskId;
        [SetUp]
        public void init()
        {         
            Console.WriteLine("Value of x is {0}", ClassUnderTest.result);
            Console.WriteLine(ClassUnderTest.taskName + " id is " + taskId); // To be used by yourself as you want to.
            Console.WriteLine("add method task id {0}",ClassUnderTest.taskId);
        }
        [Test]
        public async void TestAdd()
        {
            int answer = await cutHandle.AddWithTask(40, 2);
            Assert.That(answer, Is.EqualTo(42));
        }        
        [Test]
        public async void TestAsyncLambdaTask()
        {
            int answer = await cutHandle.AddWithTask(40, 2);
            Assert.AreEqual(42, answer);
        }
    }
}

When Synchronous is ahead of the asynchronous...

When Synchronous is ahead of the asynchronous...make the asynchronous call wait ! :)

1, 2, 3 & 4. The unit test, TestAdd fails because it calls the async method AddWithTask which, in turn, calls the async method add.
5. This is  because the  async keyword does not ensure asynchronicity; the "await" keyword does that making sure that the method call awaits 'asynchronously' for the method call to complete.

To make the test pass, add the 'await' keyword to the Task.Factory.StartNew as in the AddWithTask method.

Please refer to the next post for the "buggy"code and the test to find the bug.

Happy unit testing with NUnit ! :)

Thursday, 4 October 2012

A sneak preview - Sample NUnit async test

Since NUnit is being made aware of C# 5 new features, here is a sample unit test on async and await.

The current NUnit downlaod may not work so wait for some time before a stable build is announced.


using NUnit.Framework;
using System.Threading.Tasks;
using System.Threading;
namespace Net45.UnitTests.Samples.Jv
{
    [TestFixture]
    public class AsyncTest
    {
        int x = 0;
        [Test]
        public async void testAddition(){                    
            Assert.AreEqual(15, await returnAdditionResult());
        }
        [Test]
        public async void testAdd()
        {
            Assert.AreEqual(17, await add(9,8));
        }
        private async Task add(int a, int b)
        {
            return a + b;
        }
        private async Task returnAdditionResult()
        {
           return await add(9, 7);        
        }
    }
}