Translate

Thursday, 4 April 2019

BDD with Jest + Cucumber & Typescript

Continuing on the previous post on the Tesla Auto Pilot crash mode malfunction, here is a working code example of the feature.

The advantage of BDD is that you can not only keep the business engaged in the development process but also ensure that there are no disputes nor any cost of change as every business requirement gets neatly described as features from which all the possible scenarios based on business rules can be elaborated into crystal clear test cases.

The other advantage, of course, is that Test Driven Development becomes easy to implement as the BDD phase effectively outlines just those test cases for code to be written against for the feature to be realized.

Here is the example scenario of the auto-pilot mode beeping if the car is in auto-pilot mode.

So, effectively, there are two scenarios for the feature test to pass -

1. The car should be on auto-pilot mode.
2. The beep should be set on only if the auto-pilot mode is on and there is an object ahead.

Remember that BDD is about testing scenarios and so we don't have asserts but expects.

npm Packages used: jest, jest-cucumber, typescript, babel
Platform: nodejs
Dev tool: VS Code
Language: English :), typescript

jest-cucumber, by default, checks all tests defined under a _tests_ folder and if one does not exist then it follows the path given in the config file or in the testMatch in the package.json file.

The feature is clearly described in a .feature file as below. Remember that the gherkin syntax of given, when, then should match the scenario described in this .feature file.


The gherkin steps are defined in the .steps. file.



The actual code to test the expectation is the source code as below:


Run the test with jest.



Now, change the scenario description.





and running the test would cause the test runner to display errors because the scenario text has changed and does not match the scenario being tested for in the .steps file.


Similarly, if the source code running the test is changed and the distance is not set, then, too, the test will fail because expectations are not met!


The code change is the commented call to the method that sets the object ahead's distance (hypothetical) and so the test will fail when it tries to match the distance between the car and the object ahead.


Similarly, if the auto-pilot mode is not set the test will fail as that is the base scenario test!

From the above, you can easily perceive that the advantages of using jest-cucumber for BDD are obvious and numerous.
  1. Business can easily stay on track with development efforts.
  2. Wastage in effort and time as well as cost is reduced due to the traceability of requirements to code and vice-versa.
  3. Code waste is reduced. Only that much code is written in the TDD phase as defined by the BDD phase.
  4. Audits become simple because of the end-to-end testing available with one click.
With scaled agile frameworks like Safe, which require BDD and TDD to be well implemented, jest-cucumber and jest are incredible tools to infuse maximum agility into the software development process.

Of course, this is not to say that other tools like SpecFlow that are used for other frameworks like .Net or Java are not good, they all serve the same purpose - of defining features, deriving scenarios, writing test cases either in gherkin form or otherwise to automate the testing of your system.

Binding the test results from the above phases along with Selenium or Acceptance/Functional tests with test coverage completes the automated requirements for DevOps.

Happy BDD-ing! :)

Sunday, 24 March 2019

BDD + UADD (also known as ATDD)

It was a long time ago that I introduced UADD to an Agile audience in a Delhi NCR Agile conference (Here is the link to the presentation) but I still remember a few reactions like, "What is UADD? We have never heard of it". It told me a few facts of the world; technology, techniques and tools are not adopted as per requirement or need but on the basis of terminology that is popular, at least in India.

Almost ten years later (during which time not one in any project that I worked on was there a mention about BDD or UADD), I came across this project that used Gherkin, Cucumber and jest to drive a BDD + TDD project but the scenarios were not elaborated as tests, which is what you can do if you use jest-cucumber.

So, here we are, I thought to myself, a completely wired, end-to-end testing tool that I had envisioned a decade back using Slim and NUnit - the tools then were obviously lacking in many respects - to increase visibility of requirements as planned and to help tracking them as the project moves forward is popular.

This made me think that now is the time to take BDD to the next level.

BDD or Behavior Driven Development is a software development technique to address requirements in an easy-to-read, conversational description of a product feature and scenarios, with steps outlined, to help complete the realisation of the feature.

But BDD or rather its form, can also be used in a non-software development context.

For instance, there was this recent BBC review of a self-driven car of Tesla that showed how the auto-pilot in the Tesla could not detect a stationary car ahead of it and crashed right into it because another moving car ahead of the Tesla had been blocking it till it swerved away at the last moment.

This demonstrates the classic lazy testing syndrome - the positive scenarios are tested but the negative ones are not - often seen with teams that are pressed to deliver or does not have deep experience in testing a system

With the BDD language, you are provided with a mechanism to put the scenarios down on paper for better visibility and due to its language, in a conversational tone, proper communication happens across the system to convey what needs to be tested because when the behavior of the system is under test then the stakeholders range from business to laymen who do not understand the technical jargon.

Let me elaborate how BDD helps in the Tesla scenario

Scenario 1
Given
the car is in auto-pilot mode,
When a stationary car is ahead (distance not mentioned in this scenario)
Then brakes should be applied or an alert should be sounded

Scenario 2
Given the car is in auto-pilot mode,
When a stationary car is ahead at a distance of 10 meters (distance mentioned in this scenario)
Then brakes should be applied or an alert should be sounded

Scenario 3
Given the car is in auto-pilot mode,
When a stationary car is ahead at a distance of 5 meters (distance mentioned in this scenario)
Then brakes should be applied or an alert should be sounded

Scenario 4
Given the car is in auto-pilot mode,
When a stationary car is ahead at a distance of 3 meters (and so on)
Then brakes should be applied or an alert should be sounded

BDD is about establishing a communication with all the stakeholders in the system under development. It is all about increasing collaboration between all the stakeholders including the customer.

In the above example, it is so clear that any inexperienced person in the team may conclude that scenario 1 is all that is needed and a little more experienced may conclude that the four scenarios completes it but not so.

The biggest anti-pattern when using BDD is to write the scenarios in isolation.

The four scenarios, especially from 2 - 4, highlight the fact that a base scenario of applying instant brakes when any object, stationed at any distance less than already tested for, from the self-driving car, completes the quality assurance required.

Monday, 18 June 2018

Single page web app to single file web app

If the concept of a single page website was a novelty, then the single file web app is a wonder.

Without using the commonly used terms for describing the single file web app, let me describe what the file does -

1. it listens to a request using the HTTP or the https protocol and can respond with JSON. Is it a REST API?
2. it can contain multiple route handlers for a web request. A web server?
3. it is written in plain javascript or es6. A node.js web app?
4. it uses express.js to handle the request, response. A node.js web server?
5. it spins itself up as and when required to serve requests. Wait! Is it an appEngine?
6. it provides for modular services. Ok! Is it microservices?
7. it is a function that can handle web requests hosted on the cloud.

Alright, it is a lambda function or a cloud function.

What the Google Cloud Function (GCF) does as a FaaS (Function as a Service) is well-documented but it is in the enhancement of the DX (Developer eXperience) that the GCF scores hugely.

For an architect, it helps ensure that there are no async calls on the main app.js file, or promises used that don't get fulfilled because the app.js is the main server file that is only concerned about setting up the server and to start listening after running through a sequence of synchronous flow.

Like the moron in the '3 idiots' movie (Hindi movie) who simply rattles off memorized words, from a prepared speech in an unknown language, as it got interpreted in its mind, without bothering to understand the meaning of the sentences used, the app.js file in the node.js, expressjs context, simply runs through all the statements, dumbly - its sole purpose being to reach the end of the file for the magical server.listen statement!

Not so with the GCF.

The GCF simply spins up, executes the lines, intelligently, and once the request, response cycle is done, it shuts down by itself. So, no worries about load testing or listening to requests when there are none as in the app.js context or bothering about server resources! The GCF is a serverless server.

The GCF handles thens and catchs but most importantly, with its ability to act as a route handler, with the help of Firebase-functions, it completes the requirement for the most robust, lean web server - a single file web server. The GCF, by itself, cannot handle/parse parameters or query strings passed via the URL, but with firebase, it can!

Here is a simple GCF [Edit: link removed] - Edit: One of the pitfalls is managing the connections in a cloud function as each time, a new container instance may execute the Cloud function causing new connections with the Cloud Database server so, it becomes more than challenging to keep or share db connections!

Of course, the workaround is the infamous "Allow access from anywhere" option but then this is where the prudence in using something like a firebase library lies because it enables authorization token to be submitted in the request URL and so the infamous workaround may actually become an ideal workaround if not the solution.

And yes, with the GCF, you can query external databases in other cloud regions like a Mongodb Atlas database and the speed of the response is phenomenal! 

Thursday, 3 May 2018

A binary converter in typescript and a reference to blockchain

While writing a binary to a decimal converter in Typescript, I came across the idea of using the example of a class of students in which every student is given a binary value and asked to convert it to a decimal value.

Add a little imagination to the idea and you can come up with an interesting parallel of how a BlockChain node functions - imagine a guy not sure if the steps that he has used to convert a binary to a decimal value is correct or not and asks the nearest neighboring girl for the answer and she gives him the SHA256 hash value of, let's say, 268 (the solution), the decimal equivalent of 100001100, which is 8b496bf96bbcc9e5ac11c068b6cfb00c32f9d163bb8a3d5af107217499de997a!

Now, the guy has the hash value and knows that till his steps yield the decimal value whose sha256 hash value matches the hash given to him, he must process the steps. This, in effect, explains what happens in mining a blockchain node.

Anyway, the code is as below: (Edit: a note on refactoring: although the code has been written with a unit test and the test was written first, it is only partially refactored, for reasons of obfuscating the logic.

Point is, many bots or maybe just humans ;) mine for code but don't bother to even leave a note of thanks and when I noticed this way back in the early 2000s, I did not bother to correct Blogger's tendency to eat up the angular brackets as used in C code where the #include statements require the < and > and even changed all the return statements to return 1 instead of 0. Make them think, don't you think? :))

// binaryconverter.ts

export default class BinaryConverter{
convertBinaryToDecimal(n){
let z=1,b=0,val=0, zeroFlag=false
b=n.length-1
for (let a in n){
var num=0
for (num=b;num>0;num--){
z*=2*n[a]
}
if (num==b){
z=0
zeroFlag=true
}
else if (num!=b){
val+=z
z=1
}
b--
}
if (zeroFlag==true && n[n.length-1]==1)val++
return val;
}
}

and the mocha test,

import BinaryConverter from '../src/ComputeBinary.ts'
import {expect} from 'chai'
describe('Computation test',()=>{
it('to check if binary conversion is successful', ()=>{
var b=new BinaryConverter()
var bin='100001100', binResult=0
binResult=b.convertBinaryToDecimal(bin)
expect(binResult).to.equal(267)
})
})

The test result: I include the screenshot, usually, to complete the cycle of learning for the reader as the command line switches and flags, if not known, will not compile or may produce a different output.

If your test does not run from your default installation, install typescript and ts-node using npm install - explained in previous posts related to typescript.


I will try to build on this example with a blockchain reference in future posts