Quickly generate test data using Angular - Ronald James

Quickly Generate Test Data Using Angular

Quickly Generate Test Data Using Angular

Generate test data using Angular

I needed to generate 10,000 lines of some random test data, that still needed to make sense. Usually I would use some db technique, but I thought, being a front-end developer, why not use the browser. It truly demonstrates the power of using javascript libs. This is how I set it up.

Today you will see no screenshots because somehow my instance of WordPress gives a jQuery error when accessing my Media library. This is no real blocker, as I usually only display code with highlighting. For now, plain text just have to do.

Contents

  • Set up Angular and Bootstrap
  • Add UI Grid
  • Add the module
  • Add the controller
  • Add the factory
  • Conclusion

Set up Angular and Bootstrap

The quickest way to set up Angular is to use CDN links, not having to download any code, just one html file with this contents:

<!DOCTYPE html>
<html lang=”en-US” ng-app=”ngGenerateData”>
  <head>
    <!–angular–>
    <script src=”http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js”></script>
    <!–bootstrap–>
    <link rel=”stylesheet” href=”http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css” />
    <script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js”></script>
    <script src=”http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js”></script>

Add UI Grid

Just the same as adding angular and bootstrap, you can add the ui-grid, that will show the results in a table.

<!–ui-grid–>
<link rel=”stylesheet” type=”text/css” href=”https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.css”>
<script src=”https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.js”></script>

Add the module

Angular modules are somehow called ‘app’. We need to initiate the module by using the angular.module statement. No need to create variables, just this line will do. Not that there’s no semicolumn at the end. This will allow chaining.

<!– Custom script –>
<script>
  angular.module(‘ngGenerateData’, [‘ui.grid’,’ui.grid.exporter’])

Add the controller

From this, we can chain the controller. Take extra care in all the brackets. .controller is a function, that takes two arguments: a name and an array. In the array you can pass first the config-, then the run block. This is called dependance injection.

  .controller(‘bodyCtrl’, [‘$scope’,’$rootElement’, function ($scope, $rootElement) {
    // Full code here.
    $scope.ngName = $rootElement.attr(‘ng-app’);

    $scope.gridOptions = {
      enableGridMenu: true,
      exporterCsvFilename: ‘myFile.csv’,
      exporterCsvColumnSeparator : ‘;’,
      // exporterCsv
      exporterCsvLinkElement: angular.element(document.querySelectorAll(“.custom-csv-link-location”)),
      onRegisterApi: function(gridApi){
        $scope.gridApi = gridApi;
      }
    };

    $scope.gridOptions.data = [];
    for(var i =0; i<1000; i++) {
      $scope.gridOptions.data.push({
        ‘header’:  ‘value’
        ,’header2′: ‘value2’
      });
    }
  }]); // End of bodyCtrl

Add the factory

When we want to add reusable functionality, best is to add a factory. If you add independent services, you end up having to add all the services you want to use in the config and run block of the controller. A factory can look like this:

.factory(‘myFactory’, function(){
  return {
    uuid: function () {
      function s4 () {
        return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
      } // End of s4
      return s4() + s4() + ‘-‘ + s4() + ‘-‘ + s4() + ‘-‘ +s4() + ‘-‘ + s4() + s4() + s4();
    }, // End of uuid
  } // factory return
}); // End of factory

Now we can add it in the controller

.controller(‘bodyCtrl’, [‘$scope’,’$rootElement’,’myFactory’, function ($scope, $rootElement, myFactory) {
  // you can access the methods my calling myFactory
  console.log(myFactory.uuid());
}]);

Conclusion

In my opinion, using only one html-file doesn’t add the complexity of multiple files and gives overview of such a short application. Also no libraries are needed to be downloaded by using the content delivery network (CDN). Having to no no styling whatsoever because we use bootstrap and bootstrap out of the box looks great. With some simple lines of code you can easily generate huge amounts of test data.

Note that this test data is of high quality. Users don’t enter data like a robot, they make mistakes, or deliberate ‘damage’ data using for example starts to prefix so the records are easily found back.

Below here is the full program:

<!DOCTYPE html>
<html lang=”en-US” ng-app=”ngGenerateData”>
  <head>
    <!–angular–>
    <script src=”http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js”></script>
    <!–bootstrap–>
    <link rel=”stylesheet” href=”http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css” />
    <script src=”https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js”></script>
    <script src=”http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js”></script>
    <!–ui-grid–>
    <link rel=”stylesheet” type=”text/css” href=”https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.css”>
    <script src=”https://cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.js”></script>

    <!– Browser settings –>
    <title>Angular Project</title>
    <meta http-equiv=”X-UA-Compatible” content=”IE=edge”> <!– If IE use the latest rendering engine –>
    <meta name=”viewport” content=”width=device-width, initial-scale=1″> <!– Set the page to the width of the device and set the zoom level –>

    <!– Custom script –>
    <script>
      angular.module(‘ngGenerateData’, [‘ui.grid’,’ui.grid.exporter’])
        .controller(‘bodyCtrl’, [‘$scope’,’$rootElement’,’myFactory’, function ($scope, $rootElement, myFactory) {
          $scope.ngName = $rootElement.attr(‘ng-app’);
          console.log(“initiated bodyCtrl”);

          $scope.gridOptions = {
            enableGridMenu: true,
            exporterCsvFilename: ‘myFile.csv’,
            exporterCsvColumnSeparator : ‘;’,
            //exporterCsv
            exporterCsvLinkElement: angular.element(document.querySelectorAll(“.custom-csv-link-location”)),
            onRegisterApi: function(gridApi){
              $scope.gridApi = gridApi;
            }
          };

          //empty array assignment
          $scope.myData = [];
          $scope.gridOptions.data = $scope.myData;

          //generate test-data
          for(var i =0; i<1000; i++) {
            $scope.myData.push(getNewLine());
          }

          //get one line
          function getNewLine() {
            var car = myFactory.getLeaseCar();
            var id = myFactory.uuid();
            var budget = myFactory.getBudget();
            var priv = myFactory.getPrivateKM();
            var train = myFactory.getTrainKm();
            var usage = myFactory.getUsage(car.fuelType);
            //console.log(car.type, usage);
            return {
              id:id
              //,rules:”1a, 2c, 4b, 5a”
              ,licence: car.licenceplate
              ,carType: car.type
              ,carFuel: car.fuelType
              ,carOutput: car.CO2combinedExaust
              ,budgetTotal: budget.budget
              ,budgetSpend: car.carCost
              ,privKm: priv
              ,trainKm: train
              ,totalLiters: Math.round(usage.totalLiters * 100) /100
              ,totalMileage: Math.round(usage.totalMileage * 100) / 100
              ,totalSpend: Math.round(usage.totalSpend * 100)/100
              ,budgetLeft: budget.budget – car.carCost
              ,pricePerLiter: usage.totalSpend == 0 ? 0 : usage.totalSpend / usage.totalLiters
              ,usage: usage.totalLiters == 0 ? 0 : usage.totalMileage / usage.totalLiters
              ,amountOfTankings: usage.amountTankings
              //,fuelUsageMitigation:”100%”
              //,bonusFuelBudget:”100%”
              //,malusFuelBudget:”50%”
              //,malusPrivateKM:”0.10″
              //,bonusPrivateKM:”0.05″
              //,bonusTrainKM:”0.05″
              //,averageDieselPrice:1.099
              //,averagePetrolPrice:1.486
              //,budgetPrivateDistance:1000
            }
          }
        }]) //bodyCtrl
        .factory(‘myFactory’, function(){
        return {
          uuid: function(){
            function s4() {
              return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
            }//s4
            return s4() + s4() + ‘-‘ + s4() + ‘-‘ + s4() + ‘-‘ +s4() + ‘-‘ + s4() + s4() + s4();
          }, //uuid
          getLeaseCar: function() {
            items = [
              {licenceplate:”84-XSG-5″,type:”Renault Megane”,fuelType:”Diesel”,CO2combinedExaust:90,carCost:630}
              ,{licenceplate:”84-XSG-6″,type:”Peugeot 107″,fuelType:”Petrol”,CO2combinedExaust:99,carCost:567}
              ,{licenceplate:”84-XSG-8″,type:”Ford Galaxy”,fuelType:”Petrol”,CO2combinedExaust:167,carCost:700}
              //,{licenceplate:”84-XSG-9″,type:”Toyota Prius Plus”,fuelType:”Benzine/Elektriciteit”,CO2combinedExaust:96,carCost:523}
              ,{licenceplate:”84-XSG-1″,type:”Volkswagen Polo”,fuelType:”Diesel”,CO2combinedExaust:89,carCost:500}
              ,{licenceplate:”11-AAA-1″,type:”Peugeot 308 SW”,fuelType:”Diesel”,CO2combinedExaust:104,carCost:500}
              ,{licenceplate:”11-BBB-1″,type:”Volkswagen Passat”,fuelType:”Diesel”,CO2combinedExaust:106,carCost:650}
            ];

            //return random lease car
            return(items[Math.floor(Math.random()*items.length)]);
          }, //getleaseCar
          getBudget: function() {
            items = [
              {budget:650}
              ,{budget:650}
              ,{budget:650}
              ,{budget:650}
              ,{budget:500}
              ,{budget:500}
              ,{budget:800}
            ];

            //return ramdom lease car
            return(items[Math.floor(Math.random()*items.length)]);
          },
          getPrivateKM: function() {
            var main = Math.floor(Math.random()*4);
            switch(main) {
              case 1: return Math.floor(Math.random()*100);
              case 2: return Math.floor(Math.random()*300);
              case 3: return Math.floor(Math.random()*1200);
              default: return 0;
            }
          },
          getTrainKm: function() {
            var main = Math.floor(Math.random()*6);
            switch(main) {
              case 1: return Math.floor(Math.random()*200);
              default: return 0;
            }
          },
          getUsage: function (fuelType) {
            function getAmount() {
              var baseTankingLiters = 30;
              var tankingDiff = (Math.floor(Math.random()*40))-20;
              return(baseTankingLiters + tankingDiff);
            }

            function getPrice(fuelType) {
              //console.log(fuelType);
              var priceDiff = Math.random()/10; //+/- 20 cent
              switch (fuelType) {
                case “Diesel”: return(1.099 + priceDiff);
                default: return(1.486 + priceDiff);
              }
            }

            function getMileage(liters) {
              //randomness, 0..-4
              var offset = Math.random()*-4;
              var kmPerLiter = 18.86792452830189 + offset;
              return liters*kmPerLiter;
            }

            var totalLiters=0,totalMileage =0, totalSpend = 0;

            var amountTankings = Math.floor(Math.random()*6);
            //vary on amount of tankigs
            for(var i=0;i<=amountTankings;i++) {
              var tankingAmount = getAmount();
              //console.log(“getAmount()”, tankingAmount);
              var pricePerLiter = getPrice(fuelType);
              //console.log(“getPrice()”, pricePerLiter);
              var tankingPrice = tankingAmount * pricePerLiter;

              var distance = getMileage(tankingAmount);
              //console.log(“getMileage()”, distance)

              //add to totals
              //console.log({tankingAmount,tankingPrice,distance});

              totalLiters += tankingAmount;
              totalMileage += distance;
              totalSpend += tankingPrice;
            }
            return {
              amountTankings: amountTankings+1
              ,totalLiters: totalLiters
              ,totalMileage: totalMileage
              ,totalSpend: totalSpend
            };
          }
        } //factory return
      }); //factory
    </script>
  </head>

  <body ng-controller=”bodyCtrl”>
    <div class=”page-header”>
      <h1>Angular Project: Generate Test Data with CSV export</h1>
    </div>
    <!– the grid –>
    <div ui-grid=”gridOptions” ui-grid-exporter></div>
    </div>
  </body>
</html>


Thanks to Praveen Kumar for being our guest writer this week.

Book in for a free 10-minute candidate attraction call with us today? Please click here to make an appointment.

© Ronald James Ltd. 09824756. Q16 Business Exchange, Quorum Business Park, Newcastle upon Tyne, Tyne and Wear, NE12 8BX, United Kingdom. Website by Outlines Design.