Translate

Showing posts with label TDD. Show all posts
Showing posts with label TDD. Show all posts

Wednesday, 15 May 2019

CI/CD - Travis, Jenkins, GitHub, Cloud, DevOps

DevOps is the latest sensation happening in the software development realm not just because of the fascinating array of tools that need to be used to implement a SCM strategy but in the immense challenge that it presents to teams that are on the Agile way of software development.

In frameworks like SAFe, that has a systems view, the importance of DevOps is immense especially when SAFe could encapsulate Behavior Driven Development (BDD), Test Driven Development (TDD), Scrum, XP, Kanban in itself to deliver a solution.

There are many ways of integrating code in a SCM repository but the key factor is in selecting the right tools to have an efficient set of pipelines to enable all aspects of the Agile Software Development Lifecycle.

Traditionally, Continuous Integration(CI) means checking out, checking in, committing code and to ensure that the build always succeeds and the code base is clean for the entire team to use, whenever, wherever and whichever tool they want to access the code from. However, things are not as hunky-dory as it looks because when you check out the tools that are available in the market, including the Cloud based ones, they appear to be free and easy to use so, at first glance, it does look all rosy.

For instance, Jenkins has a cool interface that clearly tells the user on which SCM repo to use.



But the real trick is in enabling the access to the SCM for the tool.

Jenkins is an integrator that works on a different machine from the one where your code is hosted - eg., GitHub and so authenticating the CI tool to access the repository's status, code, scripts important and since Jenkins is a separate server by itself, credentials cannot be passed as is. So, what is required is for a secret that only the two tools know so that they could authenticate against a key generated using a standard cryptographic algorithm like a SSH key.



The same key is with the GitHub repository as part of your configuration of the GitHub account.



The difference between the various tools like Jenkins, Travis, Azure DevOps etc is in the way your build configuration is expected to be.

In Travis, for example, the travis.yml contains all the build steps in the form of a yaml script, which means that as long as the virtual machine understands the script, you can just about configure anything, from code coverage to tests to installation of npm packages or not, to running a mongod instance and test results as an Istanbul report, for example.

This configuration script is expected by Travis to be part of your code repository to which it is synchronized with. If there is no travis.yml then Travis will default to Ruby.



The travis.yml contains the script that tells the Travis CI container how to run the build.





And the travis.yml script does many things like installing nodejs packages (which can also be set to ignore with a gitignore file in the repo), connecting to a mongodb instance and importing some json data to running a mocha test and providing a code coverage report.

Jenkins, on the other hand, provides for the build environment, build triggers and build actions and post actions within its interface. And since Jenkins gels well with Maven and the Java environment, its usage requires a good knowledge of the Java development tools, environment like maven, the JDK and the scripts to execute the build.





But unlike Travis, which is more suited for open source projects, Jenkins is a more specialized CI tool.

The commonality in all DevOps tools is in the integration of a CI tool with a SCM repository and with a Cloud storage container to enable Continuous Deployment (CD), the usage, though, will differ as per the depth in the software development process of the team.

Below are some important questions that could serve as a checklist when deciding on what kind of a DevOps environment that you want setup for your organization/team?
  1. Does the team wish to map its BDD or TDD into an automated environment?
  2. Is there an automated build that is wired with the testing framework and the code coverage tool ?
  3. Are deployments to the cloud monitored or automated and to what extent is quality ensured in the release to deploy?
  4. How often is the release to deploy planned?
  5. What are the planned pipelines in the build that cannot be ignored or skipped and who are the responsible members in the team?
  6. Does the responsibility or accountability in anyway compromise the agility in the team?
  7. What are the recovery mechanisms or policies in place for the CI/CD pipelines?
  8. To what extent does the organization want traceability from requirements to deployment?
More on the DevOps Deployment stage in the next post.

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! :)

Thursday, 27 April 2017

BDD + TDD +UADD - Part I

It is rare that different frameworks can be wired together without facing some glitch in the implementation path. Sometimes, the technologies pose problems, some other times, the tools are not available.

For instance, on a previous occasion, I tried the three with the combination of Slim, C#, NUnit and it developed hiccups because, being a web application, the Javascript/jQuery code could not be as fluently unit tested even though I tried Jasmine and Slim posed yet another problem in that it required separate DLLs to be created for the functional tests to happen, which was far too cumbersome because it meant that components were getting created just so that some tests [to make a framework work] could be performed.

Not what a good design is - you do not create components to make tests succeed, you create components to make the system function properly!

The key to creating a great design, the Agile way, is to let the tests drive the design, not just the development. This can be possible only by getting the requirements right, right upfront. To achieve this, BDD (Behavior Driven Development) framework comes handy.

In this context, naming this framework as a Testing Behavior [Business Driven Behavior] for better User Acceptance (TBUA) would be the closest acronym to describe it.

BDD 

There are many tools and definitions that go around for BDD.

The most famous ones are

1. promise,
2. given, when, then...,
3. should and expect


style of unit testing and,

what I consider to be true behavior driven development -

4. scenario testing based unit tests.

The flavors are different with the intent same - that of providing for as many tests as possible for any given requirement [line of code].

For instance, a Business requirement is to open a XML file, read the contents and get a string as result.

The test scenarios for this business requirement are as follows:

1. Check if file exists
2. Check if file is an XML [filename contains .xml extension]
3. Check if valid XML
4. Check if string generated from XML


The difference between the BDD [without scenario testing] and the BDD [with scenario testing] is highlighted in the above screenshot.

The scenario as described by the Business Rule is to check if the file exists.

But since there is only the business requirement available at this stage, and no coding done yet, the method "openFile" does not exist. What this means is that BDD helps track the business requirements correctly. With scenario tests, it becomes easier to keep the development strictly within the business context.

The scenario has been documented in fitnesse's slimjs tool. Expand the scenario name



This part of the BDD is so essential because it helps trace the entire lifecycle of development from the time the Business Analyst comes up with the business rules based on the requirements and elaborates the scenarios for user acceptance to the time when UACs are contested over.

The rest of the scenarios are


The scenario, check if file extension is xml, does not call a method because it is well possible that it would be handled by the openFile method.

This choice is what makes the Agile way of development so different because deferring the decision till later when coding actually will reveal the possibilities through design evolved from unit tests, allows for a higher code quality.


At this point of the lifecycle, the BDD has just started. Some scenarios have been obtained from user stories and scenario tests have been written for it.

The main reason for writing scenario tests is so as to be able to wire up the scenarios with functional tests, after the unit tests [part of TDD] have completed.

Please note it is not necessary to do scenario testing to do BDD; it just enhances the Agile experience more.

Next part: Deriving unit tests from scenario tests






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
    }
}