Monday, September 12, 2016

QA: Decision Tables as specification-based test design technique

Let's start with definitions, per ISTQB glossary:
Decision Table Testing: A black-box test design technique in which test cases are designed to execute the combinations of inputs and/or stimuli (causes) shown in a decision table.
Decision Table: A table showing combinations of inputs and/or stimuli (causes) with their associated outputs and/or actions (effects), which can be used to design test cases.
This technique is using to test all possible combination of conditions, relationships, and constraints. Decision tables usually applied for the integration, system and acceptance test levels. Also, this technique could be used for component testing.
The table should describe relationships between conditions and actions.

Template of Decision Table:
Decision Table Template











Example:
Decision Table Example











At least one test case should be created for each column. The number of tests will increase in case of boundaries values in conditions. Boundary Value Analysis and Equivalence Partitioning are additional to the Decision Table technique

Type of defects: functional and non-functional defects

Wednesday, September 7, 2016

Setting up Visual Studio Code for TypeScript development


Install TypeScript compiler

To setup TypeScript on your computer, you need to setup node.js with npm. There is a good article, which will help you to do that, please find it using following link: Installing Node.js and updating npm. 
We just installed node.js and updated npm. So we are ready to install TypeScript on your computer. If you want you can install the latest build of TypeScript. To do that you have to run following command:

npm install -g typescript@next #install nightly build

Although you have the possibility to install nightly builds, I would recommend installing the latest stable version of the language. To do that type following command in cmd.exe and hit enter:

npm install -g typescript #install the latest stable version

Install Visual Studio Code with extensions


GulpTsLintVisual Studio Code

Visual Studio Code

Let's install Visual Studio Code first. You can download and install it from https://code.visualstudio.com.

TSLint

An extensible linter for the TypeScript language. TSLint supports:
  • custom lint rules
  • custom formatters (failure reporters)
  • inline disabling / enabling of rules
  • configuration presets (tslint:latest, tslint-react, etc.) & composition
For more info please use http://palantir.github.io/tslint/

To install TSLint extension: Open Visual Studio Code → Navigate to Extensions tab on left sidebar → Type 'TsLint' in search text-box → Install extension.


To make extension work you need to install tslint globally. To do that run in cmd.exe tool the command:

npm install -g tslint #installing tslint globally

Gulp Snippets

We are going to use Gulp to compile our TypeScript code, so let's install Visual Studio Code extension to help us with Gulp syntax.
Open Visual Studio Code → Navigate to Extensions tab on left sidebar → Type 'Gulp Snippets' in search text-box → Install extension.


Creating the project

First of all, you need to create the project folder. I will create mine with the name "TypeScriptBlog". Create the folder and open it in cmd.exe tool. Now we need to create package.json file. To do that run in cmd.exe command:

cd path/to/project
npm init

Open created folder in Visual Studio Code and check created file. It should contain something like this:

{
  "name": "typescriptblog",
  "version": "1.0.0",
  "description": "Blog engine written on TypeScript",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MIT"
}

We are now ready to install the third party dependencies:

npm install  --save-dev typescript
npm install  --save-dev tslint 
npm install  --save-dev gulp
npm install  --save-dev gulp-tslint
npm install  --save-dev gulp-typescript

Compiling the project

Create gulpfile.js in the project's  folder and copy following  content to it:

var gulp = require("gulp"),
    tslint = require("gulp-tslint"),
    tsc = require("gulp-typescript");

var tsProject = tsc.createProject("tsconfig.json");

gulp.task("build-app", function () {
    return gulp.src([
        "app/**/**.ts"
    ])
        .pipe(tsc(tsProject))
        .js.pipe(gulp.dest("app/"));
});

// Rebuild project on any ts file changed
gulp.task('watch', function() {
  gulp.watch("app/**/**.ts", ['build-app']);
});

Create tsconfig.json file and copy following content to it:

{
    "compilerOptions": {
        "sourceMap":  true
    }
}

Now we can build our application. Press Ctrl + Shift + P in Visual Studio Code → Type "Run Task" → run "build-app" task. If you want to rebuild your code each time when any file changed, execute task with name "watch".


To test that the Gulp is working you can use following files. Create app folder in the root folder and add files to app folder.

greeter.ts


class Greeter {
    constructor(public greeting: string) { }
    greet() {
        return "<h1>" + this.greeting + "</h1>";
    }
};

var greeter = new Greeter("Hello, world!");
    
document.body.innerHTML = greeter.greet();

greeter.html


<!DOCTYPE html>
<html>
  <head><title> TypeScript Greeter </title></head>
  <body>
    <script src='greeter.js'></script>
  </body>
</html>

Project structure



Linting the project

Earlier we installed all necessary tools for linting. Now it is time to configure them. Open cmd.exe and execute command:

cd path/to/project
tslint --init

After that you can find that tslint.json file was added to the solution. This file contains default linting settings, if you would like to extend or change them, please use https://palantir.github.io/tslint/rules/ for more info.
One more thing what we can do. We want tslint be executed using Gulp, so open gulpfile.js file and add the following code to it:

// Linting the project
gulp.task("lint", function () {
    return gulp.src([
        "app/**/**.ts"
    ])
        .pipe(tslint({
            formatter: "verbose"
        }))
        .pipe(tslint.report())
});

If 'lint' task does not appear in the task list, restart Visual Studio Code and try again.

Сonclusion

Now we know how to setup Visual Studio Code with TypeScript. With this article, I open a cycle of articles about TypeScript, in which we are going to create blog engine written on TypeScript. All the code you can find under repository https://github.com/aliakseimaniuk/TypescriptBlog

Thursday, September 1, 2016

QA: Boundary Value Analysis as specification-based test design technique

Let start from definition, per ISTQB glossary:
Boundary value analysis (BVA): a black-box design technique in which test cases are designed based on boundary values.
 Boundary Value: an input or output value which is an the edge of an equivalence partition or at the smallest incremental distance on either side of an edge, for example the minimum and maximum value of a range
This technique is an extension of equivalence partitioning technique.  There are two approaches of BVA exists:
  • Two values testing.  Only two values selected for each boundary: one value on the boundary and the previous/following value outside the partition. For example, if an equivalent partition is integer range from 10 to 15, the following values should be tested: 9 (outside of the partition), 10 (boundary); 15 (boundary), 16 (outside of partition). Short description: MIN-1; MIN; MAX; MAX+1; Where "1" is the minimal incremental value
  • Three values testing. This approach uses 3 value as the basis. One value outside of the boundary, the second value is boundary value, and the third value is inside of partition. For example, if the equivalent partition is an integer from 10 to 15, the following value should be tested: 9 (outside of the partition), 10 (boundary), 11 (inside of boundary); 14 (inside of boundary), 15 (boundary), 16 (outside of partition).Short description: MIN-1; MIN; MIN+1; MAX-1; MAX; MAX+1; Where "1" is the minimal incremental value 
Which approach to select? The approach should be selected based on Risks which are associated to tested items. 3-values approach should be selected for the highest risks.
VBA could be applied for ONLY for ordered equivalent partitions. Type of ordered equivalent partitions:
  • Numeric attributes of non-numeric variables (e.g., length) 
  • Loops, including those in use cases 
  • Stored data structures 
  • Physical objects (including memory) 
  • Time-determined activities

Type of defects: functional and non-functional

Sunday, August 28, 2016

Get IP address by MAC address in C#. Updating ARP table.

Recently I have written article about getting IP address of connected to the network device using it MAC address, you can find it using the following link Get IP address by MAC address in C#. It seemed to me that the solution was good until I figured out that it requires some time for ARP table being updated.
To reproduce such situation you just need to reboot your computer or execute command:
arp -d

Run cmd.exe as administrator, type command text and hit enter. Now the code provided in the previous article does not work as expected.

Fixing the issue


The device should be on the same sub-network as running computer. So we need to ping all the IP addresses int the sub-network, e.g. (192.168.1.1 - 192.168.1.255) to update the ARP table. I have updated IpFinder class with necessary code.

IpFinder.cs


using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace SftpDownloader.Core
{
    public class IpFinder
    {
        public string FindIpAddressByMacAddress(string macAddress, string currentIpAddress)
        {
            Parallel.ForEach(GetListOfSubnetIps(currentIpAddress), delegate (string s)
            {
                DeviceScanner.IsHostAccessible(s);
            });

            var arpEntities = new ArpHelper().GetArpResult();
            var ip = arpEntities.FirstOrDefault(
                a => string.Equals(
                    a.MacAddress,
                    macAddress,
                    StringComparison.CurrentCultureIgnoreCase))?.Ip;

            return ip;
        }

        private List<string> GetListOfSubnetIps(string currentIp)
        {
            var a = currentIp.Split('.');
            var lst = new List<string>();

            for (int i = 1; i <= 255; i++)
            {
                lst.Add($"{a[0]}.{a[1]}.{a[2]}.{i}");
            }

            lst.Remove(currentIp);

            return lst;
        }
    }
}

DeviceScanner.cs


using System.Net.NetworkInformation;

namespace SftpDownloader.Core
{
    public class DeviceScanner
    {
        public static bool IsHostAccessible(string hostNameOrAddress)
        {
            Ping ping = new Ping();
            PingReply reply = ping.Send(hostNameOrAddress, 1000);

            return reply != null && reply.Status == IPStatus.Success;
        }
    }
}

Thursday, August 25, 2016

How to create a bootable USB drive for Windows 10 without any 3rd party tools

It is easy to create bootable USB drive for Windows 10 without any additional tools. Just use built-in functionality.
  1. Plug in your USB device
  2. Run cmd.exe (Command Prompt) as administrator
  3. Open the disk management utility, type in diskpart and hit enter
  4. Get connected disks that are available – to do that, type in list disk and hit enter
  5. Select your USB drive – to do that, type select disk # and hit enter – you’ll have to replace the # with your disk number
  6. Clean the USB drive – to do that, type clean and hit enter
  7. Create a bootable partition – type in create partition primary and hit enter
  8. Select the partition that you just created. To do that, type in select partition 1
  9. Type active and hit enter
  10. Format the USB drive – type in format fs=fat32 and hit enter. It takes some time to complete formatting.
  11. Assign your USB drive a letter, to do that, just type in assign
  12. Copy all the Windows 10 files and paste it inside the USB drive
That is all you need to do.

Sunday, August 21, 2016

.NET async repository using MongoDb

Intro

In this article we will learn how to create async repository for MongoDB as datasource. More info about MongoDb you can find using following link https://www.mongodb.com/. All code from this article you can find using link https://github.com/aliakseimaniuk/MongoRepository.

Repository interface

Instead of classic CRUD methods I prefer to use next repository interface. 

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using MongoRepository.Domain.Entities;

namespace MongoRepository.Domain.Repositories
{
    public interface IRepository<TEntity, in TKey> where TEntity : IEntity<TKey>
    {
        Task<TEntity> GetByIdAsync(TKey id);

        Task<TEntity> SaveAsync(TEntity entity);

        Task DeleteAsync(TKey id);

        Task<ICollection<TEntity>> FindAllAsync(Expression<Func<TEntity, bool>> predicate);
    }
}
To be sure that entity is the good fit for the repository we introduced the IEntity interface. Repository entity should implement the specified interface.
namespace MongoRepository.Domain.Entities
{
    public interface IEntity<TKey>
    {
        TKey Id { get; set; }
    }

    public interface IEntity : IEntity<string>
    {
    }
}

Base repository implementation

As we created generic repository interface, we expect that all the repositories will work in the same way. Please find below the implementation of base repository.

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoRepository.Domain.Entities;
using MongoRepository.Domain.Repositories;

namespace MongoRepository.Persistence.Repositories
{
    public abstract class BaseMongoRepository<TEntity>
        : IRepository<TEntity, string> where TEntity : IEntity
    {
        protected abstract IMongoCollection<TEntity> Collection { get; }

        public virtual async Task<TEntity> GetByIdAsync(string id)
        {
            return await Collection.Find(x => x.Id.Equals(id)).FirstOrDefaultAsync();
        }

        public virtual async Task<TEntity> SaveAsync(TEntity entity)
        {
            if (string.IsNullOrWhiteSpace(entity.Id))
            {
                entity.Id = ObjectId.GenerateNewId().ToString();
            }

            await Collection.ReplaceOneAsync(
                x => x.Id.Equals(entity.Id),
                entity,
                new UpdateOptions
                {
                    IsUpsert = true
                });

            return entity;
        }

        public virtual async Task DeleteAsync(string id)
        {
            await Collection.DeleteOneAsync(x => x.Id.Equals(id));
        }

        public virtual async Task<ICollection<TEntity>> FindAllAsync(
            Expression<Func<TEntity, bool>> predicate)
        {
            return await Collection.Find(predicate).ToListAsync();
        }
    }
}
You might notice, that BaseMongoRepository class has abstract property Collection. This property is representing the data collection of the entities and should be implemented in the derived classes.

Custom entity repository

Previously I mentioned that all derived from BaseMongoRepository class classes  should have Collection property. To get that I created MongoDataContext class.

using System.Configuration;
using MongoDB.Driver;

namespace MongoRepository.Persistence
{
    public class MongoDataContext
    {
        public MongoDataContext()
            : this("MongoDb")
        {
        }

        public MongoDataContext(string connectionName)
        {
            var url = 
                ConfigurationManager.ConnectionStrings[connectionName].ConnectionString;

            var mongoUrl = new MongoUrl(url);
            IMongoClient client = new MongoClient(mongoUrl);
            MongoDatabase = client.GetDatabase(mongoUrl.DatabaseName);
        }

        public IMongoDatabase MongoDatabase { get; }
    }
}

Finally we are ready to implement our custom repository class. I will create PersonRepository as example.

using MongoDB.Driver;
using MongoRepository.Domain.Entities;

namespace MongoRepository.Persistence.Repositories
{
    public class PersonRepository : BaseMongoRepository<Person>
    {
        private const string PeopleCollectionName = "People";

        private readonly MongoDataContext _dataContext;

        public PersonRepository(MongoDataContext dataContext)
        {
            _dataContext = dataContext;
        }

        protected override IMongoCollection<Person> Collection =>
            _dataContext.MongoDatabase.GetCollection<Person>(PeopleCollectionName);
    }
}

namespace MongoRepository.Domain.Entities
{
    public class Person : IEntity
    {
        public string Id { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }
    }
}

MongoDb settings


MongoDb version: 3.2.5
C# MongoDb driver version: 2.2.4

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="MongoDB.Bson" version="2.2.4" targetFramework="net452" />
  <package id="MongoDB.Driver" version="2.2.4" targetFramework="net452" />
  <package id="MongoDB.Driver.Core" version="2.2.4" targetFramework="net452" />
</packages>

Tuesday, August 16, 2016

QA: Equivalence Partitioning as specification-based test design technique

Let start from definition, per ISTQB glossary:
Equivalence partitioning: a black-box test design technique in which test cases are designed to execute representative from equivalence partitions. In principle, test cases are designed to cover each partition at least once. 
 What does it mean?

Inputs, outputs, internal values and time-related values should be split into equivalent groups, where values on boundaries and inside of group will lead to the same result.
Each equivalence partition should be tested with valid and invalid values at least once. Multiple values for a single partition doesn't increase the coverage percentage.

Benefits: number of tests significantly descrise

Data set was split into 2 subset with selection of test case of each subset

Equivalence partitioning

Data set was split into 2 major subsets and 2 subsets of one of major subsets

Equivalence partitioning

Difficulties which can be faced: participation was identified incorrectly. That could mean that invalid values accepted or valid values rejected by the system.

Avoid errors:
a. Subsets shouldn't have a common elements. Each sub set should have unique data elements
b. Subsets shouldn't be empty. Element should exists in data set
c. Subsets union should be equivalent to original set

Types of defect: functional defects