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

Translate

Saturday, 13 December 2014

Yo, l'il Marie!

Yo, l'il Marie!
See, if you don't talk to me,
that dirt truck gonna come mash me
and then you will see what you don't wanna see.

There will be no Rocky Balboa,
and in your eyes no glow
to say, " ****** creepo!"
so talk to me, even if only to say, "Oh!"

Yo, l'il Marie!
Don't talk to me,
if you wanna see the dirt truck mash me
and if you wanna see what you don't wanna see.

It is important to hit
harder than you get hit.
Bother not a bit
if your life is not so well lit.

Yo, l'il Marie!
There doth come a fairy,
when your mind is airy
and dreams coax you to marry.

These streets that you fanned,
with curls and frills unmanned,
and a future unplanned,
need your steps be more manned.

Yo l'il Marie!
believe you me
your fears will flee
and you will be less lonely.

Yo, l'il Marie!
Don't you see?
all that you see
is all that you see.

Friday, 5 December 2014

$.when then and then JavaScript...a single-threaded-monolith-of-interpreted-disaster-for-maintenance :) !

The funny thing is that when JavaScript and jQuery are used in conjunction, it can often be a little puzzling as to which event is getting propagated when and whether to use event propagation or event bubbling to ensure that the right sequence of events have been handled or not and when all these aspects did get resolved, as I sat back to contemplate on the immense, combined destructive power of JavaScript and jQuery together not through any power tools but in the way that they resolve each others' problems such that the end result looks more like a compound that could have confounded the best of scientists put together, I realized that that here is an example that could be likened to the splattering of debris from space, to the 'distributed' missile that "Iron Man" goes to demonstrate to the terrorists, to the 'open for interception' messages strewn across the social media that eventually conjoin (if such a word exists) like in the Terminator (the villainous ones who roll back from liquid droplets to human form!) and serves, best, as the prototype to the theory that if art is a reflection of life then software, AI and design patterns (software ones that is) are 'represented' algorithms of human's interactions. 

Tough and tasking, this may be, I can understand, especially if you are reading my blog with a cuppa and thought it would be a breeze to read through my blog ! 

But it was necessary, believe you me, this roundabout, Thomas Hardy-like obscurity-bordering-on-controlled-rant narrative because it is only upon describing the problem statement in detail can you understand or comprehend what the above observation, and the title above it, means !

The problem statement is the usage of two asynchronous mechanisms (not methods) that need to 'listen' (change in location position co-ordinates), 'communicate' (save the change in location to the DB) 'intelligently' (i.e., not as a dumb client that can simply wait for any response and 'redirect' as if passing the blame to the next page!) through an AJAX call to a VB.Net WebScript Service method (which means server-side technology) via JavaScript, as a JSON object, and to finally (the compound), ensure that the GeoLocation call has been successfully completed before calling the Web Service Script method and on return (I had never experienced before (in my mind, that is) how many different places that a call to a function could return to - a JavaScript call can return to any DOM object, it can return to the last line of the calling function, it can return to a callback, 

(Ah, we all know that? Read on for a few minutes more and you will realize why dismissive attitudes are not only demeaning to progressive minds but also needless !))

behave like the dancing hurricane (or typhoon) that deceives to deceive - that is quite a lot of integrity for a scripted, interpreted language,

despite all that junk said about JavaScript being a single-threaded-monolith-of-interpreted-disaster-for-maintenance - ah, so here we are,

So. when a call to a location services and a call to save the consolidated data occur synchronously but also must ensure that the save data will occur only upon successful location seek, the one best way that is known to be used is the 'callback' - which is much like an illusion in JavaScript because, whether you like it or not, the subsequent lines of code after the location seek will be executed.

For instance,

// Lines n to n+25 in "some .js file"
function somefff....{
    if (navigator.geolocation) {
        var positionOptions = {
            enableHighAccuracy: true
        };
Line 1     navigator.geolocation.getCurrentPosition(function success1(position) {
                var brlat = position.coords.latitude;
                var brlongitude = position.coords.longitude;
                sessionStorage.setItem("breakStartlocation", brlat + "," + brlongitude);
             }, function (err) {
                 showError(err);
                 wctr = true;
                 sessionStorage.setItem("breakStartlocation", strlocationErrorMessage);
            },positionOptions);
        } else {
              alert("Location setting is not enabled or supported in your current browser!");
        }

// Lines n+26 

 Line n if (confirm("You have disabled location seek. Press Ok to reset your browser settings or Cancel to deny location information.")) {

}

else if ....{}

// Lines n+200 to 30 (or so!)

        options.success = function (result) {
            alert("Break saved");
        }
        options.error = function (err) { alert("Error");}
Line n+1        setTimeout(function() {
                          $.ajax(options)},3000);
                        }
Line n+1+1 (for the sake of brevity!)

return saveResult;

}

In the above lines of code, Line 1, Line n and Line n+1 and Line n+1+1 fall into a sequence because of JavaScript's execution mechanism, despite the logical requirements, which is to ensure the sequence of the calls. Not a big deal, as the flippantly inexperienced may quickly quip not knowing that the Geolocation provider has made their service an async service, by specs and design!

This means that the calling code or object would have continued on to display the Confirm message, without waiting for the user to acknowledge to the browser (that has already received the location provider's request to seek out the user's location) that their location could be sought.

It also means that the Line n+1 Ajax call to the webservice method is already underway (even the Confirm dialogs can be of no use if the user clicks the Ok buttons real fast!) and while we are at it, we may as well consider the fact that the Ajax call may have already returned back to the calling page ie. Line n+1+1, too, has executed. So, the calling page that has to display (render) a different set of buttons and UI elements (CSS elements), must have a mechanism to determine if the save data call has been a success and here, is where jQuery and Ajax come to the rescue of JavaScript.

The zest for patching up is an age-old technique that has both its 'pros' and 'cons' (probably why it is called the 'jugaad' in India) and this zest is evident with the way many JS developers and designers felt and being more seamlessly tuned to each other's needs than the 'boxed' up Microsoft or Java developers, jQuery is almost the way a poor man or woman cater to their family, a 'patch' here, a patch there - "Oh, does the event bubble up to the document object? ('Daya', in Hindi, means compassion but since CID, a Hindi TV serial of monumental moronity, has become symbolic of a person breaking open doors, unlawfully, it has now become synonymous with 'show some compassion for wooden doors'. What I mean is, desist. Desist from that lust to argue that a Document is part of the DOM.). Let us change the Ajax calls to return to the DOM than to elements or objects..."

This comparison is not meant to be derogatory because it is a "kind of" representation of how nature, too, responds (though in a more perfectly harmonized manner), adjusts and responds to adjustments again (much like the shifting of the tectonic plates to create mountains to change the paths of rivers to cause floods to cause erosion again to level up).

So, to keep the thread of continuity tight as I lead you through this incredible maze of Ajax event handlers, DOM and plain old JavaScript timeouts, let me quickly warm you up to the "Promise" offered by AJAX/jQuery.

Unlike the build-up, this post's ending is pretty abrupt - all you need is a $.when to wrap around the method call  -

// The calling method from another page (can also be interpreted as a DOM, for the sake of understanding this example.) From different page.aspx

$.when('methodTocall').then(func,func1); 


and a .then() with func and func1 representing the 'success' and 'not success' in the function call when it completes! So, what is the promise? All this can be handled with simple callbacks.

The 'Promise' is that you can line up any number of sequence to calls made to asynchronous methods

(ie., methods that make asynchronous calls but which desperately need a mechanism, not provided in JavaScript, that execute async calls, synchronously, but require coherence in sequence to enable manageable logic in execution, not just to tackle complex business models and demands but also for the benefit of testing frameworks and testability)!

but more importantly, as I experienced, I could manage two 'disconnected' events that had 'committed' synchronous activities attached, 'post-' the async call, that relied not on the 'traditional' HTML post or 'form' methods or elements but on CSS elements, which meant callbacks-had-to-'trigger'-an-execution-thread on the client-side upon successful completion (or not), which cannot happen until it happens at the DOM level and which the Ajax's document level event handlers like AjaxStart, AjaxStop, AjaxComplete, AjaxSuccess and many more provide.

But the real joke is in the parameters to the then() method - they, too, execute synchronously !! :D

Wednesday, 3 December 2014

A normal life, after all...

(Dedicated in aid of the victims of the Bhopal tragedy, who need lifelong support and help.)

A terrible, terrible sight
a terrible, terrible plight
it is not a matter of right
nor is it a matter of oversight

if riches are given more weight
over nature's might
then such, that does not become a human sight,
becomes the common's terrible, terrible plight.

Utter not nor hear not nor listen not to no evil
See not nor show not nor teach not to know evil
Make not nor buy not nor sell not no evil
Let not nor allow not nor bear not no evil

for the devil is not in the evil
nor in the 'evil' preached as the devil
the evil is the evil
not preached nor practiced nor known as 'evil'.

Normal work that lead to tragedies
normal play end in disaster
but time flies, faster,
to leave normal life that usually dies

all well said and done and taken in the right spirit,
but this terrible plight, that, that makes such a sight
that does not become common sight, a common, every day plight
still persists to be known as an 'oversight'.

Sunday, 30 November 2014

How to add dynamic rows in Javascript

One of the most curious case has come my way and it pertains to many aspects of software development but most importantly, to testing and the purpose of testers so I think this post becomes necessary as due to online projects and work done more than earlier, many 'unqualified' testers are giving 'opinions' on projects like 'user feedback' on products.

It is also possible that before going 'live' some project owners try to get 'user feedback' to make their system more robust, in which case, it can only be called an 'innovative' approach, but which obviously is more often than not called 'too smart' or 'too stupid' because what is applicable on a 'product development life cycle' is usually not applicable for a 'project development life cycle' and the resulting confusion can only be called 'immaturity' and 'malignant' because it only gives 'support' for 'excuses' made by the project owners to manipulate the 'quality' of delivery to their teams or to vendors or to service providers.

Many testers take it upon themselves to take 'moral' stands, where the issue is either a bug or a feature that may not be working properly. They are 'conveniently' backed by 'time to market' and 'management' theories on how much it costs them if their product is delayed and so undue pressures and compromises and 'jugaads' are initiated.

The whole point is in 'planning' and many get it right and many do not, as happens in the whole software development life cycle of any project.

So, when a solution 'demands' that rows must be added to a table and must be infinite in number upon the click of a user action at the client-side, Javascript and jQuery are the best languages (everybody in the software industry acknowledges this and knows it!) but the problem is how to test a scenario where the events, data and the actions themselves are to be dynamic.

I know, as do many mature Agile developers, that I can use Jasmine to unit test Javascript.

The 'wise' know the pitfalls and prepare a 'plan' to take care of the 'unforeseen' bugs that may occur at runtime for which it becomes important to be 'proactive' enough to identify the 'run time' aspects of the scenario and instead of preparing 'contingency' plans to mitigate the possible delay that may or would be caused by the complexity, they, instead, prepare 'plans' to 'corner' the developers. Seriously !

And many actually 'glare' at others who may know the technique and can do it but they themselves cannot!!

Now, why is such arrogance necessary when you can do your simple work properly by identifying test scenarios and have them tracked in a Google doc or a project management bug tracking system rather than indulging in blame games. The answer could be in the political atmosphere that surrounds a company or some problem totally unrelated to the project or work but which can be identified and best solved by the people themselves.

A question that normal people's culture and etiquette does not allow and some try to take advantage of it all that since the management or the HR are not tech savvy, they can get away with 'bluster' and 'bravado'.

And this is why it is necessary for HRs of organizations to read blogs and consult 'experienced' and 'mature' people before hiring and not rely on Facebook and other 'rigged' references. I remember when working with an organization, I would be called upon plus shared with, the technical and technological plans of projects and the necessary plans for the HR and the teams to make.

Simple thumb of rule for young developers or testers is be humble to ask for help. politely. When you have established yourself then you can go around stomping on everyone's feet but when it is time to learn, do not teach others more capable than yourself ! :)

All that is required is to understand your position and be humble enough to ask for help from other team members, and not 'grand stand' around that such scenarios cannot be tested or even developed !

The greatest disservice anybody could do to their team or even friends and family is to not admit that they were wrong but instead persist with blaming others for their own incapability in either 'testing' or in technique unless of course, hiring 'goons' to enforce that others do it for you without having to pay for the service and without admitting to your own incapability (as happens in Indian movies, where a 'goon' becomes a Doctor by having somebody else taking the medical entrance test to become a MBBS doctor) is an option available for you.

So, it does not even make it lack of knowledge or inexperience or immaturity but sheer 'unprofessional' attitude that does not exist in the IT industry.

I have had this experience and so speak from first hand experience that it is tantamount to a kind of 'cunning' and 'cleverness' that no management would want to associate with, so if you wish to make a career in the IT industry, do not indulge in such practices nor allow others, who may be doing it 'secretively' from 'outside'.

Here is one scenario, where you can add any number of rows to a table, using Javascript (knowledge of Html, JS, jQuery and CSS is required to run the example) and which somebody seems to have professed as 'impossible' and then trying too darned hard to prove themselves right!

// the output as it should be

                          








// Javascript


                        // HTML string to add to table breaks
                        var strBreak = null;
                        var strTxtBreak = null;
                        var rowTxt = null;

                        // used for determining number of rows added to table
                        var xx = 0;

                        // used for calculating distance of textboxes
                        var jk = 5;

                        // used for array index

                        var cell3 = "
";
                        for (var i = 0; i < w; i++) {                      
                            row = table.insertRow(i);
                            strBreak = "
 +
";
                            jk = jk + 5;
                            strTxtBreak = "

";
                            row.innerHTML = strBreak + strTxtBreak;
                            yy = yy + 2;
                            xx = i;
                            jk = jk - 5;
                            jk = jk + 55;
                        }
                        var j = 0;
                     
                        j = xx+1;
                        // Row for Notes
                        var rowN = table.insertRow(j);
                        //var rowN1 = table.insertRow(j+1);

                        // For vertical ruler

                        //var t1cell1 = "
";

                        // Set initial position values of elements
                        notesIconLeftValue = 14;
                        notesIconTopValue = jk;
                        notesAreaLeftValue = 40;

                        // creating style str for Notes
                        styleStrForNotesIcon = "style=" + "'position:absolute;top:" + notesIconTopValue + "px;left:-14px;" + notesIconLeftValue + ";" + "'";
                        styleStrForNotesArea = "style=" + "'position:absolute;top:" + notesIconTopValue + "px;left:" + notesAreaLeftValue + "px;width:310px;height:65px;text-align:left;background-color:lightgray;border-color:lightgray;'"
                        var cell5 = "
";

                        // HTML for Notes box row
                        var strNotesIcon = "
 +

";
                        var strNotesArea = "

"

                        // Inserting Notes row HTML
                        rowN.innerHTML = strNotesIcon + strNotesArea;
                        //rowN1.innerHTML = t1cell1;
                        jk = jk + 50;

                        // HTML for buttons
                                             
                        // Table 'tablebtns' into which to add buttons
                        var table1 = document.getElementById("tablebtns");
                        var k = jk + 55;
                        var l = k + 55;

                        // For continue shift button
                        var m = jk + 30;
                        var nn = m + 25;
                        var t1row1 = table1.insertRow(0);
                        // Table style and position
                        var cell1 = "
 +
Continue Work
";
                        t1row1.innerHTML = cell1;

                        eDiv.appendChild(table);
                        eDiv.appendChild(table1);

                        $('#box1').show();
                        $('#tablebrks').show();
                        $('#tablebtns').show();
                        document.getElementById("continueWork").onclick = clickContinueWork;

// HTML
<html>
     <div id="boxMiddle">
         <table style="position:absolute;top:10px;left:25px;width:305px;display:none" id="tablebrks">
         </table>
     </div>

        <table id="tablebtns" style="display:none"></table>

<style>

#box1 {    position:absolute;
    height:110px;
    top:180px;
    padding: 5px 5px 5px 5px;
    border:none;
    margin:25px;
    background-color:white;
    display:none;
}

#boxMiddle {
    position:relative;
    height:260px;
    /*top:145px;*/
    padding:4px 7px 2px 4px;
    border:none;
    margin:25px;
    background-color:white;
    display:none;
}

div.calloutContinue {
    background-color: #8EC127;
    background-image: -moz-linear-gradient(top, #444, #444);
    position: absolute;
    top:30px;
    left:42px;
    color: #000000;
    padding: 10px;
    border-radius: 3px;
    /*box-shadow: 0px 0px 20px #8EC127;*/
    margin: 25px;
    min-height: 20px;
    /*border: 1px solid #333;*/
    text-shadow: 0 0 1px #000;
    text-align:center;
    height:40px;
    width:145px;
}
.calloutContinue::before {
    content:"";
    width: 0px;
    height: 0px;
    border: 0.4em solid transparent;
    position: absolute;
}

.calloutContinue.right::before {
    left: -16px;
    top: 10%;
    border-right: 10px solid #8EC127;
}
.calloutContinue.right:hover {  
    cursor:pointer;
}
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">

// The javascript code here

<script/>

Friday, 31 October 2014

1500 and Counting (no, not Tigers)

The most popular post in my blog is the one that has no tags to help search engines find it !! :)

Eh, what Google?

And I paid for Google AdWords spending an hour to figure out the right words to use ! :D

Wednesday, 29 October 2014

A little more CSS magic !

One of the coolest things about CSS and jQuery is the simplicity that you can achieve in design.

Here is an example of a simple timeline that I created with css



The vertical line is not a .gif or an image but a line drawn, given co-ordinates in pixels.

The CSS for the same is in this fiddle that I have created for you to play around with.

And with a little jQuery, the animation of the timeline becomes simply simple!

Saturday, 4 October 2014

The Repository Pattern - I (The Interface and ConcreteRepository)

The use case for a repository can be many - code, books, project etc but it is when these repos need to be combined and managed that the Repository pattern begins to make sense and the SharpRepository and the Unit of work technique to maintain/manage transactions for the different repositories, gain importance.

How the aggregate is defined and managed is how the question of whether 'one size fits all?' question will get an answer.

Although there is nothing new that could probably be added to the many excellent resources on the SharpRepository implementation, I did find some curious elements that were not as well or as clearly implemented in the many available resources on the web. This is the simplest of them all.

I will post my code first and continue with the explanations inline as and when and where I found it necessary.

The example that I have chosen is dependent on many interfaces and concrete implementations so posting the fully tested code will be done in stages.

The interface

using System.Collections.Generic;

namespace LinqExpressionsHashSet
{
    interface IRepository<T>
    {
            T GetById(int id);
            T GetByName(string name);
            IEnumerable<T> GetAll();
            IEnumerable<T> FindAll(IDictionary<string, object> propertyValuePairs);
            T FindOne(IDictionary<string, object> propertyValuePairs);
            T SaveOrUpdate(T entity);
            void Delete(T entity);  
    }
}

The concrete repository

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using SharpRepository.Repository.Queries;

namespace LinqExpressionsHashSet
{
        public class Repository<T> : IRepository<T>,IEnumerable<T> where T : class,IIdentifiable,new()
        {
          // for InMemoryRepository testing
            private readonly HashSet<T> data;
            private readonly IQueryable<T> queryableData;

        public Repository()
            : this(Enumerable.Empty<T>())
        {
        }
        public Repository(IEnumerable<T> testData)
        {
            data = new HashSet<T>(testData);
            queryableData = data.AsQueryable();
        }

        public Expression Expression { get; private set; }

        public Type ElementType { get; set; }

        public IQueryProvider Provider { get; private set; }

        public void Add(T entity)
        {
            data.Add(entity);
        }

        public void Add(IEnumerable<T> entities)
        {
            foreach (var e in entities)
            {
                data.Add(e);
            }
        }

        public void Update(T entity)
        {
            data.RemoveWhere(i => i.Id == entity.Id);
            data.Add(entity);
        }

        public void Update(IEnumerable<T> entities)
        {
            foreach (var e in entities)
            {
                Update(e);
            }
        }
        /* To use for Unit of Work
        public IBatch<T> BeginBatch()
        {
            return (IBatch<T>)data.ToList<T>();
        }
        */
        public void Delete(T entity)
        {
            data.RemoveWhere(i => i.Id == entity.Id);
        }

        public void Delete(IEnumerable<T> entities)
        {
            foreach (var e in entities)
            {
                data.RemoveWhere(x => x.Id == e.Id); // The id is from MongoDB
            }
        }

        public T Find(Expression<Func<T, bool>> predicate, IQueryOptions<T> queryOptions = null)
        {
//            Extracting the lambda expression
            Expression<Func<T, bool>> ep = Expression.Lambda<Func<T, bool>>(predicate);
            // without queryOptions
            return queryableData.First(ep);
        }

/*
            //Need to test this
        public TResult Find<TResult>(Expression<Func<T, bool>> predicate, Expression<Func<T, TResult>> selector,
                                     IQueryOptions<T> queryOptions = null)
        {
            Expression<Func<T, TResult>> ep = Expression.Lambda<Func<T, TResult>>(selector);
            IEnumerable<TResult> someResults = queryableData.Select(selector);
            Expression<Func<T, bool>> exp = Expression.Lambda<Func<T, bool>>(predicate);
            TResult tt = default(TResult); // to escape uninitialized compiler error and null.
            foreach (TResult a in someResults)
            {
                var e = queryableData.First(exp);
                if (data.Contains(e))
                {
                    tt = a;
                    break;
                }
            }
            return tt;
        }
*/
        public bool Exists(Expression<Func<T, bool>> predicate)
        {
            Expression<Func<T, bool>> ep = Expression.Lambda<Func<T, bool>>(predicate);
            Func<T, bool> fexp = ep.Compile();
            var t = fexp(new T()); // Returns bool from the expression

            return t; // This is not the correct return value. Used only to pass the compiler.
        }

            /* To be used with EF
            protected DbSet<T> DbSet;

            public Repository(DbContext dataContext)
            {
                DbSet = dataContext.Set<T>();
            }
         
            public void Insert(T entity)
            {
                DbSet.Add(entity);
            }

            public void Delete(T entity)
            {
                DbSet.Remove(entity);
            }

            public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
            {
                return DbSet.Where(predicate);
            }

            public IQueryable<T> GetAll()
            {
                return DbSet;
            }

            public T GetById(int id)
            {
                return DbSet.Find(id);
            }
             */
        }
    }

and an identifiable interface for in memory and MongoDB implementation. This could be substituted with an IEntity interface that can help provide the 'id' but on this (the BS, that is :)) I will post later. This is being used to query an expression with an 'id' in the Delete method above.

// The Identity interface

using MongoDB.Bson;
namespace LinqExpressionsHashSet
{
    public interface IIdentifiable : IIdentifiable<ObjectId>
    {
        string StringId { get; }
    }
    public interface IIdentifiable<T>
    {
        T Id { get; }
    }

}

// The Project repo
using System;

namespace LinqExpressionsHashSet
{
    public class Project:IIdentifiable
    {
        public int projectId { get; set; }
        public string name{get;set;}
        public DateTime createdOn { get; set; }
        public string createdBy { get; set; }
    }
}

More to follow...:)

Wednesday, 1 October 2014

The de-generations

It must be a serious set of nutcases that are going around asking "Do you write your own blog?". The level of intelligence has de-generated to such an extent that it is not even worth mentioning to look at the paradox in the question - how can it be my blog if I do not write it ? :D

Go, bite elsewhere or go get your brains or head examined and if there is no cure, just take the damn thing off your shoulders (or have it taken off you there are many obliging psycho morons around nowadays), it is not worth carrying that much weight...:D

Monday, 25 August 2014

What to Unit test?

Going by the book is not really encouraged in today's wildly advancing technology world. If you, do, it will most probably leave you staring at the behinds of many. :)

Best way to keep yourself ahead is to be really good in your skill set; if it is a programming language, be on top by participating in discussion forums and communities. This will help knowing about scenarios that may never appear in your own project or lifetime.

Close to what I am getting at is this definition of unit tests by Martin Fowler -
Like most software development terminology, however, it's very ill-defined, and I see confusion can often occur when people think that it's more tightly defined than it actually is. 
First and foremost,  what to unit test depends on your commitment to testing. If you are very committed then chances are that your code coverage will be good. But over and above this,  you also need the skill with the unit test tool. For instance, the most common statement possibly used by almost all programmers across the world is the if (!fileExists) or within a try...catch block.

Is this statement testable? Should it be tested? To answer the second question first, the reason the answer is 'Yes' is because the line of code is expected to throw many exceptions -  DirectoryNotFoundException, FileNotFoundException and (yes) etc...So, the first question becomes important - is it testable?

Again, the answer is 'Yes' (left out italicizing it to make it more interesting! :)) but if you really do not know any syntax of existing unit test tool, how to write the test?

This question has always seemed important to me (to make a programmer move from the "Code-first syndrome" to a "Test-first-and-let-the-test-tell-you-what-code-to-write avatar") and so, I decided to list (well, sharing just one technique now (how to get and test a list of files from the file system in a unit test)...will share more later) here some of these common scenarios.

Aside from helping the code achieve the necessary quality benchmarks, unit tests should also be efficient and lean so that it does not weigh down the overall build or CI framework.

So, to write a unit test in the 'file exists' scenario,

1. If not file exists

Scenarios - as many as there are files (wild possibilities! :)) in a specified directory.

So, the unit test will want a list of files against which to test for some criteria.

The code will be something like this -

using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace NUnit_Tests
{
    public class ClassUnderTest
    {            
        public List getListOfFiles()
        {
            string[] filePaths=null;
            filePaths = Directory.GetFiles(@"c:\cambridge\");
            return filePaths.ToList();
        }
    }
}

In  NUnit, here is an example of how to test the method most efficiently and ALSO in such a way that maximum scenarios can be tested with this approach !!

using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
namespace NUnit_Tests
{
    [TestFixture]
    public class TestClass
    {
        ClassUnderTest objInstance;
        string[] filesToExist = { "abc.jpg", "a.htm" };
        [Category("LongRunning")]
        [Test]
        public void LongRunningTest([ValueSource("Files")] string filePath)
        {
            Assert.That(Files.ToList().LastOrDefault(),Is.EqualTo("zzz.jpg"));
        }

        private IEnumerable Files
        {          
            get
            {
                objInstance = new ClassUnderTest();
                return objInstance.getListOfFiles();
            }
        }
    }
}

The snapshot below (before refactoring class names) shows the number of scenarios (equivalent of unit tests / asserts in NUnit or unit testing tools) that are now possible with this approach.



For example, you could test if the path is returned correctly with Is.SamePath or can test the number of files existing or if a particular file has a required extension and the possibilities are endless.



Sunday, 24 August 2014

KnockoutJS and AutoPostBack="true" - I

I had to check this out. What could be the difference if the developer were to use KO and not ASP.Net?

The only difference is the programming language of use - C# or jQuery / Javascript.

The resultant output is this below


No button click event just the AutoPostBack property of the drop down list set to true.

I will first share the ASP.Net code and then dwell into the equivalent KO code.

You need JSon.Net installed and referenced to the project, an app_id to consume the JSon data resultset from openexchangerates.org, VS 2012 for web and you are good to go.

The HTML source of the .aspx page

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="GetExchangeRates.aspx.cs" Inherits="GetExchangeRates" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
        Currency  
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
        </asp:DropDownList>
  
        <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

    
    </div>
    </form>
</body>
</html>


Here is the aspx code behind.

using System;
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;
    public partial class GetExchangeRates : System.Web.UI.Page
    {
        static JSon_SampleData.CurrencyRates obj;
        Dictionary rateValues;
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                obj = new JSon_SampleData.CurrencyRates();
                obj = Download_Serialized_ExchangeRate("http://openexchangerates.org/api/latest.json?app_id=");
                rateValues = new Dictionary();
                rateValues = obj.Rates;
                foreach (var raate in rateValues)
                {
                    DropDownList1.Items.Add(raate.Key);
                }
                Session["rateValues"] = rateValues;
            }
        }

        private static T Download_Serialized_ExchangeRate(string url) where T : new()
        {
            using (var w = new WebClient())
            {
                var json_data = string.Empty;                
                try
                {
                    json_data= w.DownloadString(url);
                }
                catch (Exception) { }
                return !string.IsNullOrEmpty(json_data) ? JsonConvert.DeserializeObject(json_data) : new T();
            }
        }

        protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
        {
            rateValues = (Dictionary)Session["rateValues"];
            foreach (var raate in rateValues)
            {
                if (raate.Key == DropDownList1.SelectedItem.Text)
                {
                    TextBox1.Text = raate.Value.ToString();
                    break;
                }
            }

        }
}


And the Class to hold the JSon data.

using System.Collections.Generic;

namespace JSon_SampleData
{
    public class CurrencyRates
    {
        public string Disclaimer { get; set; }
        public string License { get; set; }
        public int TimeStamp { get; set; }
        public string Base { get; set; }
        public Dictionary Rates { get; set; }
    } 
    
}

Reference the JSon Data class in your ASP.Net website.

I will post the KO code in the next part and get back to the BDD and Agile part.