"No one is harder on a talented person than the person themselves" - Linda Wilkinson ; "Trust your guts and don't follow the herd" ; "Validate direction not destination" ;

February 24, 2012

Note on success of GUI automation

There are plenty of blogs which recommend
  • When to Automate, At what stage of project execution (working feature set, stable application etc..)
  • What to Automate, How to identify a test case for automation (repeatable steps, stable feature, regression cases, BVT cases etc..)
This post is a example on determining quality of automation suite. This stackoverflow answer is my motivation for this post
 
Joe Strazzere answer is simple, straight forward and portrays real world scenario. Below is snap of the answer underlined important lines in my perspective
 
 
What to focus on Automation 
  • Tests focusses on basic scenarios and slowly extending to cover end to end functionality
  • Execute 10~15 core functional scenarios
What not to focus on automation
  • Merely focussing one existence of ids
  • Testing the front end without connecting underlying layers
What is good automated test case ?
  • Login to online shopping portal
  • Search for products (query the DB to fetch products)
  • Invoke web service involved to fetch results
  • Compared returned results in UI vs Web Service Results
What is not efficient automated test case ?
  • Login to online shopping portal
  • Search for products which are hardcoded
  • Compared returned results in UI with predetermined hardcoded results
If you find your automation tests pass and your manual test identifies bugs then it is a indicator for automation test cases improvement. What matters is Quality not Quantity !!
 
Happy Learning!!! 

February 11, 2012

Telerik Test Studio Webinar

There are lot of test Tools available in market. I attended Telerik Test Studio session. The tool is focussed on Microsoft Platform (Web Testing WPF/Silverlight). Session was useful to understand Product Portfolio, features

Notes from the Session
  • Overview and benefits of test automation covering rerunning test cases, reduce test execution efforts, eliminate human error etc..
Test Studio
  • Inbuilt Scheduling Engine
  • Performance Test Support
  • Integration withing TFS
  • Cross browser testing support
  • Microsoft Platform focussed test product (WPF/Silverlight)
  • Data Driven Testing Support
More Details - Link
 
Express Edition Features
  • Available as a VS plugin
  • Generate unit test cases which can be run using NUnit, XUnit, MbUnit
Demo
  • Record and playback of Web Test was demonstrated in the session
  • This made me to remember VSTT web test record and play back feature
It would be interesting to download and Evaluate Telerik Free Testing Framework
 
Happy Learning!!

February 09, 2012

Tool Developer Notes - Part III

[Previous Post in Series - Tool Developer Notes - Part II]
[Next Post in Series - Tool Developer Notes - Part IV]

Adding few more interesting notes based on learning's

Tip #1 - Working with DateTime Picker in C#. Requirement was to write in specific format. Provided below is an example using WinForms Application


For the Submit button try out the sample code for Setting date, Adding Duration

        private void btnSubmit_Click(object sender, EventArgs e)
        {
            int duration = 0;
            DateTime CurrentTime;
            String CurDate;
            duration = Convert.ToInt32(txtDuration.Text);
            CurrentTime = dTPTimeSet.Value;
            for (int i = 0; i < 10; i++)
            {
                CurDate = CurrentTime.ToString("MM/dd/yyyy hh:mm");
                MessageBox.Show(CurDate);
                CurrentTime = CurrentTime.AddMinutes(duration);
            }
        }


Tip #2 - Check if string is GUID. Tweaking the code from Stackoverflow question

public static bool IsGuid(string guid)
        {
            if (!string.IsNullOrEmpty(guid))
            {
                Regex regex = new Regex(@"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
                return regex.IsMatch(guid);
            }
            return false;
        }

Tip #3 - Loop through all files in a directory
How to loop through all files in a folder using C#

Tip #4 - Last File Created time in a directory
using System.IO.DirectoryInfo we find last file created time in a directory

string Folder = @”C:\Test”;
DirectoryInfo dinfo = new DirectoryInfo(Folder).GetDirectories("*", SearchOption.AllDirectories).OrderByDescending(d => d.LastWriteTimeUtc).First();
//Find the Last File Created Time in Directory
DateTime LastCreatedTime = dinfo.LastAccessTime;

Happy Learning!!!

January 28, 2012

High Availablity Notes

[You may also like - Tech-Ed Talks - SQL Server Upgrade Best Practices & High Availability]

I subscribe to Brent Ozar weekly news updates. Zero Downtime Data Centre Migration caught my attention in weekly updates

How We Moved Our Data Center 25 Miles Without Downtime (High Availability)

Another Interesting Case Study is Sharepoint Performance Improvement using Aptimize Accelerator

Recently while learning on Latency came across case study.
  • They have done some optimization in terms of reducing css, JS files. 
  • Caching performance has been increased using - Aptimize Website Accelerator
  • We use a CDN already, can Aptimize help? Link
  • So combining - Best Practises, CDN, Website Accelerator aptimize would be a great combination for achieving superior performance
  • A Crash Course in Optimizing SQL Server for SharePoint
For beginners good read on latency basics is provided in post

More Reads



Happy Reading!!!

January 26, 2012

NOSQL Updates & Database Products Update - II

[Previous Post in Series - NOSQL Updates & Database Products Update]
[You may also like - NOSQL - can it replace RDBMS Databases?]

Amazon has launched its own NOSQL database - Dynamo DB . NOSQL space is growing big with multiple players launching their own NOSQL databases.

Features
  • Index management (Predictable performance Even if Data Size grows, Need to explore more to understand how this is taken care)
  • Flexible Schema (Feature common in all NOSQL databases)
  • Scalability (Scale as per your need), High Availability by having data replicated across multiple zones & Performance
  • More Detailed Notes - Get Started with Dynamo DB
  • Amazon CTO Dynamo DB introduction blogpost
More Reads - Cassandra and Dynamo Comparision

Another very good read - Top BI Trends for 2012 and a Look Back at 2011
Focus for this year 2012 BI market is
  • Mobile BI
  • Cloud BI
  • NOSQL BI Strategy
  • NOSQL Adoption (ACID compliant, cloud based DBs - NuoDB)
More Reads
Happy Reading!!!

January 14, 2012

Tool Developer Notes - Part II

Previous Post in Series - .NET App Developer Notes

Bunch of exercises and learning's encountered while developing a Tool for my work. All examples posted as simple console apps. Many of them refer back to stackoverflow learnings. This post is intended for my reference. Try / Catch block and error handling is not included in some cases.

Tip #1 - Reading First Line from a File
Program.cs
using System;
using System.Configuration;
using System.IO;
namespace ServiceExample
{
   class Program
    {
        public static void Main(string[] args)
        {
            string sourceFileNamePath = ConfigurationManager.AppSettings["sourceFileNamePath"];
            string line = "";
            int linecount;
            Program P = new Program();
            line = P.GetLine(sourceFileNamePath, 1);
            Console.WriteLine(line);
            Console.ReadLine();
        }
        public string GetLine(string fileName, int lines)
        {
            using (var sr = new StreamReader(fileName))
            {
                for (int i = 1; i < lines; i++)
                    sr.ReadLine();
                return sr.ReadLine();
            }
        }
    }
}

App.config entry
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
      <appSettings file="" >
            <clear />
            <add key="sourceFileNamePath" value="E:\\TestFiles.csv"/>
      </appSettings>
</configuration>

Tip #2 - Find Duplicates values in a line using Hash method

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
namespace TestExample
{
    class Program
    {
        public static void Main(string[] args)
        {
            char[] delimiterChars = { ' ', ',', '.', ':', '\t' };
            string line = "A A B C D E F G H";
            string[] Attributes = line.Split(delimiterChars);
            var hash = new HashSet<string>(Attributes);
            string[] uniqueAttributes = hash.ToArray();
            if (Attributes.Length == uniqueAttributes.Length)
            {
                Console.WriteLine("No Duplicate Elements present");
            }
            else
            {
                Console.WriteLine("Duplicate Elements present");
            }
            Console.WriteLine(line);
            Console.ReadLine();
        }
        public string GetLine(string fileName, int lines)
        {
            using (var sr = new StreamReader(fileName))
            {
                for (int i = 1; i < lines; i++)
                    sr.ReadLine();
                return sr.ReadLine();
            }
        }
    }
}

Tip #3, #4 - Fetching a Single (Scalar) value from DB and Fetching multiple rows

Note - In case of Error add the Assembly refereces to fix them

using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
namespace TestExample
{
    class Program
    {
        public static void Main(string[] args)
        {
            Program P = new Program();
            P.FetchScalarValue();
            P.FetchDBMethod();
        }
        public int FetchDBMethod()
        {
            try
            {
                Console.WriteLine("Fetch Multiple DB Values Example \n");
                SqlCommand comm = new SqlCommand();
                comm = SetUpConnection();
                OpenConnection(comm);
                comm.CommandType = CommandType.Text;
                comm.CommandText = @"SELECT TOP 10 [CustomerID],[NameStyle],[Title],[FirstName],[MiddleName]
                                      ,[LastName],[Suffix],[CompanyName],[SalesPerson],[EmailAddress],[Phone]
                                      ,[PasswordHash],[PasswordSalt],[rowguid]
                                  FROM [AdventureWorksLT2008R2].[SalesLT].[Customer]";
                SqlDataReader oReader = comm.ExecuteReader();
                if (oReader.HasRows)
                {
                    while (oReader.Read())
                    {
                        Console.WriteLine(oReader[2].ToString());
                        Console.WriteLine(oReader[3].ToString());
                        Console.WriteLine(oReader[4].ToString());
                        Console.WriteLine(oReader[5].ToString());
                        Console.WriteLine(oReader[6].ToString());
                        Console.WriteLine(oReader[7].ToString());
                        Console.WriteLine(oReader[8].ToString());
                        Console.WriteLine(oReader[9].ToString());
                        Console.WriteLine(oReader[10].ToString());
                        Console.ReadLine();

                    }
                }
                else
                {
                    return 0;
                }
                oReader.Close();
                CloseConnection(comm);
                return 0;
            }
            catch (Exception EX)
            {
                return 1;
            }
        }
        public void FetchScalarValue()
        {
            try
            {
                Console.WriteLine("Fetch Single DB Values Example \n");
                SqlCommand comm = new SqlCommand();
                comm = SetUpConnection();
                OpenConnection(comm);
                comm.CommandType = CommandType.Text;
                comm.CommandText = @"SELECT COUNT(1)
                                  FROM [AdventureWorksLT2008R2].[SalesLT].[Customer]";
                Console.WriteLine(comm.ExecuteScalar().ToString());
                Console.ReadLine();
            }
            catch (Exception EX)
            {
            }
        }
        public SqlCommand SetUpConnection()
        {
            string strConn = ConfigurationManager.AppSettings["ConnectionString"];
            SqlCommand comm = new SqlCommand();
            comm.Connection = new SqlConnection(
                strConn);
            return comm;
        }
        public void OpenConnection(SqlCommand comm)
        {
            comm.Connection.Open();
        }
        public void CloseConnection(SqlCommand comm)
        {
            comm.Connection.Close();
        }
    }
}

App.Config File

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
      <appSettings file="" >
            <clear />
            <add key="ConnectionString" value="Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=AdventureWorksLT2008R2;Data Source=.\SQLSERVER2008R2" />
      </appSettings>
</configuration>

Tip #5 - Best practice use of Try catch Exception handling
I like the stackoverflow question -Is this a bad practice to catch a non-specific exception such as System.Exception? Why?

Tip #6 - Status check for methods
Narrowly focussed on developing a working code without thinking of making it cleaner and better. Transition from DB to C# this is a good
learning. My learning is best described in stack overflow question - return status checking 

More Reads
Custom Load Generator
Debug http 401 Error
How to create load generator for simulating concurent hits?
Simple microbenchmarking in C#
Custom Thread Pool
Custom LoadGenerator Tool Identifies the Issues Your Application Faces Under Stress
Load testing : how to generate per second requests?
Happy Learning!!!

December 30, 2011

NuoDB Conflict Management

Continuing previous post on NuoDB, December there was another technical session on NuoDB. I had few questions on conflict management as well. I have captured my understanding in below notes.
 
Does Readers block writers ?
Every new update is stored as new version. There are no updates to existing records. This way reads do not block writes.
 
Write / Write Conflicts ?
Only after recent Write operation is completed, the next write operation would be performed
 
How long does these versions exist in memory ?
Thanks to Jim for commenting on post. He has provided the answer
NuoDB has a garbage collector that runs around deleting inaccessible record versions

  • Bottleneck of Current OLTP Databases - Lock management, this is synchronous, related queries would be blocked until Data is committed, Managing the Table structures on the Disc along with supporting ACID compliance. Again this depends on so many factors isolation levels, locks set.
  • NuoDB - MVCC based. Asynchronous mechanism. Conflict management related questions listed above provides clarity on implementation
Brokers - Load Balancing
Archive Manager - Stores data as Key Value Pair
Transaction Manager - Diskless.
  • The process of performing a transaction includes
  • Broker Notifies Transaction Manager for Transaction to be performed
  • Fetch the required ATOMS from Archive Manager
  • Load the Data into Transaction Manager
  • Perform the transactions
  • Pass it to Archive Manager and commit in DB
Session also covers brief overview of Elasticity, Virtualization, High Availability support of Nuo-DB. Benchmark results against Mysql results are a good start and a compelling reason to try out NuoDB
 
Happy Learning!! 

December 29, 2011

Command Prompt Disappears in Win7

I had this issue for last 6 months. Command prompt window used to disappear immediately after launch. This link was very useful to solve the issue.

As suggested in the answer, You have to delete the AutoRun value set as Exit in the Registry (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor).

Happy Learning!!

.NET App Developer Notes

Last couple of weeks I have been busy trying out my new project in VS2010 / C#. Couple of basic exercises for my learning purpose are listed below. Please modify the code to make it work.
Tip #1
  • Working on Folder Open and Browse Dialog for a Windows FormsApp
  • Best option is to reuse codeplex code. Link 
Tip #2
  • Working with Threads
  • Below is a Simple Threadpool (For sum of two numbers). Try it out as a Forms app so see how operations are performed parallely.
using System;
using System.Threading;
using System.Windows.Forms;
class InputNumbers
{
    public int a { get; set; }
     public int b { get; set; }
}
class Example
{
    public Example()
    {
      // Declare a new argument object.
      InputNumbers IS = new InputNumbers();
      IS.a = 10;
      IS.b = 20;
      for(int i = 0; i<100 ; i++)
      {
            IS.a = i;
            IS.b = i+2;
            // Send the custom object to the threaded method.
            ThreadPool.QueueUserWorkItem(new WaitCallback(AddNumbers), InputNumbers);
    }

    private void AddNumbers(object a)
    {
      InputNumbers IS = a as InputNumbers;
      Messagebox.show((IS.a+IS.b).ToString());
    }
}

Tip #3

To keep methods seperate, DB Layer, Web Methods and UI Layer, I decided to keep them in different classes. This question was useful for my learning for this tip. Below is a simple example.
Class A
Class B
ProgramFile.cs
All classes in different file

classA.cs
using System;
namespace class_A
{
    class classA
    {
        public void methodA()
        {
            Console.WriteLine("In Method A");
        }
    }
}

classB.cs
using System;
namespace class_B
{
    class classB
    {
        public void methodB()
        {
            Console.WriteLine("In Method B");
        }
    }
}

program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using class_A;
using class_B;
namespace ClassExamples
{
    class Program
    {
        static void Main(string[] args)
        {
            classA A = new classA();
            classB B = new classB();
            A.methodA();
            B.methodB();
            Console.ReadLine();
        }
    }
}

Tip #4
  • Working with Log4Net
  • The following two posts link1, link2 were useful to get started.
  • Below is simple Windows Forms App
  • Add the Log4Net DLL in project references
 LogHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using log4net;
using log4net.Config;
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
[assembly: log4net.Config.Repository()]
namespace loggingns
{
    public class Loghelper
    {
        #region Data Members
        public static readonly ILog testLogger = LogManager.GetLogger("log4NetExample");
        #endregion
    }
}

Program.cs
Invoke the following method to log entries . Use the namespace loggingns in Form1.cs.

using log4net;
using log4net.Config;
using log4net.Core;
using loggingns;

Sample Test method

        public void testMethod()
        {
            Loghelper.testLogger.Debug("Debug Log");
            Loghelper.testLogger.Info("Info Log");
        }
App.config file entry
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
      <configSections>
            <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
      </configSections>
      <appSettings file="" >
            <clear/>
             <add key="log4net.Internal.Debug" value="false"/>
      </appSettings>
      <!-- This section contains the log4net configuration settings -->
      <log4net debug="true">
            <appender name="LogFileAppender" type="log4net.Appender.FileAppender">
                  <layout type="log4net.Layout.XMLLayout" /> -->
                  <param name="File" value="TestLoggerExample.log"/>
                  <param name="AppendToFile" value="false" />
                  <layout type="log4net.Layout.PatternLayout">
                        <header type="log4net.Util.PatternString" value="[START LOG] %newline" />
                        <footer type="log4net.Util.PatternString" value="[END LOG] %newline" />
                        <conversionPattern value="%d [%t] %-5p - %m%n"/>
                  </layout>
                  <filter type="log4net.Filter.LevelRangeFilter">
                        <param name="LevelMin" value="INFO"/>
                        <param name="LevelMax" value="INFO"/>
                  </filter>
            </appender>
            <!-- Setup the root category, add the appenders and set the default level -->
            <root>
                  <level value="ALL" />
                  <appender-ref ref="LogFileAppender" />
            </root>
            <!-- Specify the level for some specific categories -->
            <logger name="log4NetExample">
                  <!-- <appender-ref ref="B" /> -->
                  <level value="ALL" />
                  <appender-ref ref="LogFileAppender" />
            </logger>
      </log4net>
</configuration>

I hope these tips would help for future reference.

More Reads
N-Tier Architecture Best Practices, Part 1: 2-Tier Architecture with just a Data
N-Tier Architecture Best Practices, Part 2: 3-Tier Architecture with interfaces and a Data Tier


Happy Learning!!