Friday, October 14, 2011

Integrating Javascript tests into a CLI build

Wherein we walk through a basic setup for running Javascript unit tests on the command line. After some initial investigation (here) I didn't find time to get back to Javascript unit testing until recently. I have now managed to get Javascript unit tests running fairly gracefully in a command line build at work; here is an outline of how, simplified from the "real" implementation to highlight the basics. Fortunately a great deal of the work is done for us, always nice when it turns out that way.

We are going to run everything off the filesystem to avoid having our tests impacted by external influences.

Part 1: Basic test setup
  1. Create a directory to house Javascript unit test files; we will refer to this as \jsunit henceforth when giving paths. 
  2. Download QUnit.js and QUnit.css into \jsunit
  3. Download run-qunit.js into \jsunit
  4. Create a file testme.js in \jsunit with the following content
    /**
     * var-args; adds up all arguments and returns sum
     */
    function add() {
    }
    
  5. Create a file testme.test.htm in \jsunit with the following content
    • Note we are using local filesystem paths to load all content; we have no external dependencies
    • <!DOCTYPE html>
      <html>
      <head>
      	<!-- we need QUnit as a test runner -->
          <link rel="stylesheet" href="qunit.css" type="text/css" media="screen" />
          <script src="qunit.js"></script>
      	
      	<!-- we'd like to have the file we're going to test -->
          <script src="testme.js"></script>
      	
      	<!-- and finally lets write some tests -->
      	<script>
      		console.log("test time baby");
      
      		test("add is defined", function() {
      			equals(typeof window.add, "function", "add isn't a function :(");
      		});
      	</script>
          
      </head>
      <body>
      	 <h1 id="qunit-header">QUnit Tests</h1>
      	 <h2 id="qunit-banner"></h2>
      	 <div id="qunit-testrunner-toolbar"></div>
      	 <h2 id="qunit-userAgent"></h2>
      	 <ol id="qunit-tests"></ol>
      	 <div id="qunit-fixture"></div>    
      </body>
      </html>
      
  6. Download PhantomJS (1.3.0 at time of writing)
    • For example PhantomJS commands I will assume it is on PATH (eg phantomjs args); use the qualified path if not (eg C:\where\phantom\is\phantomjs args)
  7. Open testme.test.htm in a browser; it should look like this:

  8. Open a command prompt, navigate to \jsunit and run phantomjs run-qunit.js testme.test.htm
    • Output should be similar to:
      test time baby
      'waitFor()' finished in 211ms.
      Tests completed in 57 milliseconds.
      1 tests of 1 passed, 0 failed.
      
    • Note we don't see any "test blah pass" or "test two fail" style output
Part 2: CLI build integration prep
So far so good, now we need to get setup to run in a CLI build. There a couple of things we'd like here, most of which are already implemented in run-qunit.js:
  1. Output each test pass/fail
  2. Output log messages from tests to the console
    1. This "just works" courtesy of run-qunit.js, yay!
  3. Exit with non-zero error code if tests fail
    1. This makes it easy for build to detect failure and do something in response; for example an Ant build could simply set failonerror
    2. This "just works" courtesy of run-qunit.js, yay!
We just have to setup output of test pass/fail information to the console. We'll add a test that fails to show what that looks like. Proceed as follows:
  1. Create a file test-support.js in \jsunit with the following content:
    //create a scope so we don't pollute global
    (function() {  
       var testName;
       
       //arg: { name }
    	QUnit.testStart = function(t) {
    	    testName = t.name;
    	};
    	
    	//arg: { name, failed, passed, total }
    	QUnit.testDone = function(t) {
    	    console.log('Test "' + t.name + '" completed: ' + (0 === t.failed ? 'pass' : 'FAIL'))
    	};
    	
    	//{ result, actual, expected, message }
    	QUnit.log = function(t) {
    	    if (!t.result) {
    	        console.log('Test "' + testName + '" assertion failed. Expected <' + t.expected + '> Actual <' + t.actual + '>' + (t.message ? ': \'' + t.message + '\'' : ''));
    	    }
    	};
    }());
    
  2. Edit testme.test.htm to pull in test-support.js and add a test that will currently fail
    • <!DOCTYPE html>
      <html>
      <head>
      	<!-- we need QUnit as a test runner -->
          <link rel="stylesheet" href="qunit.css" type="text/css" media="screen" />
          <script src="qunit.js"></script>
      	
      	<!-- where would our tests be without support! -->
      	<script src="test-support.js"></script>
      	
      	<!-- we'd like to have the file we're going to test -->
          <script src="testme.js"></script>
      	
      	<!-- and finally lets write some tests -->
      	<script>
      	
      		test("add is defined", function() {
      			equals(typeof window.add, "function", "add isn't a function :(");
      		});
      		
      		test("add 1+1", function() {
      			equals(add(1, 1), 2);
      		});		
      	</script>
          
      </head>
      <body>
      	 <h1 id="qunit-header">QUnit Tests</h1>
      	 <h2 id="qunit-banner"></h2>
      	 <div id="qunit-testrunner-toolbar"></div>
      	 <h2 id="qunit-userAgent"></h2>
      	 <ol id="qunit-tests"></ol>
      	 <div id="qunit-fixture"></div>    
      </body>
      </html>
      
  3. Open a command prompt, navigate to \jsunit and run phantomjs run-qunit.js testme.test.htm
    • Output should be similar to:
      Test "add is defined" completed: pass
      Test "add 1+1" assertion failed. Expected <2> Actual <undefined>
      Test "add 1+1" completed: FAIL
      'waitFor()' finished in 209ms.
      Tests completed in 70 milliseconds.
      1 tests of 2 passed, 1 failed.
    • If you print the exit code (echo %ERRORLEVEL% in Windoze) you should get a 1, indicating we have fulfilled the 'exit with non-zero exit code on failure' requirement :)
Part 3: Ant integration
At long last we are ready to integrate this mess into a build. For this example I will use Ant and will assume Ant is on PATH. At time of writing I am using Ant 1.8.2.

  1. Create a phantomjs.bat file in \jsunit with the following content
    @echo off
    C:\where\you\put\phantom\phantomjs.exe %*
    
    • Alternately create phantomjs.sh with equivalent functionality if on *nix
  2. Create a build.xml file in \jsunit with the following content
    • <?xml version="1.0" encoding="UTF-8"?>
      <project name="jsunittests" basedir="." default="main">
      	<property name="builddir" location="${basedir}/target"/>
      	
      	<condition property="phantom.filename" value="phantomjs.bat"><os family="windows"/></condition>
      	<condition property="phantom.filename" value="phantomjs.sh"><os family="unix"/></condition>   
      	
      	<target name="clean">
      		<delete dir="${builddir}"/>
      	</target>
      	
      	<target name="prep">
      		<mkdir dir="${builddir}"/>
      	</target>
      	
      	<target name="jstest">
            <!--Run all tests w/phantom, fail if tests fail. Execute all files w/extension .test.htm. -->
            <apply executable="${phantom.filename}" failonerror="true" dir="${basedir}" relative="true">
               <arg value="run-qunit.js"/>
               <fileset dir="${basedir}">
                  <include name="**/*.test.htm" />
               </fileset>
            </apply>			
      	</target>
      	
      	<target name="main" depends="clean, prep, jstest">
      	</target>
      </project>
      
  3. Run 'ant'; you should get output similar to the following (yes, it's supposed to fail, remember we have a test that fails setup on purpose)
    • Buildfile: build.xml
      
      clean:
         [delete] Deleting directory C:\Code\jsunit-trial\target
      
      prep:
          [mkdir] Created dir: C:\Code\jsunit-trial\target
      
      jstest:
          [apply] Test "add is defined" completed: pass
          [apply] Test "add 1+1" assertion failed. Expected <2> Actual 
          [apply] Test "add 1+1" completed: FAIL
          [apply] 'waitFor()' finished in 218ms.
          [apply] Tests completed in 58 milliseconds.
          [apply] 1 tests of 2 passed, 1 failed.
      
      BUILD FAILED
      C:\Code\jsunit-trial\build.xml:18: apply returned: 1
      
      Total time: 0 seconds
      
  4. Edit testme.js just enough to fix the test
    • /**
       * var-args; adds up all arguments and returns sum
       */
      function add() {
      	var sum =0;
      	for (var i=0; i<arguments.length; i++)
      		sum += arguments[i];
      	return sum;
      }
  5. Run 'ant'; you should get output similar to the following
    • Buildfile: build.xml
      
      clean:
         [delete] Deleting directory C:\Code\jsunit-trial\target
      
      prep:
          [mkdir] Created dir: C:\Code\jsunit-trial\target
      
      jstest:
          [apply] Test "add is defined" completed: pass
          [apply] Test "add 1+1" completed: pass
          [apply] 'waitFor()' finished in 214ms.
          [apply] Tests completed in 59 milliseconds.
          [apply] 2 tests of 2 passed, 0 failed.
      
      main:
      
      BUILD SUCCESSFUL
      Total time: 0 seconds
Pretty sweet, we've got Javascript tests running in an Ant build as a first-class citizen. Now if you break my Javascript my Continuous Integration server will let me know!

Part 4: Code coverage
Finally we are ready to get some code coverage. We are going to get code coverage by instrumenting our js files using JSCoverage, running our QUnit tests such that the relative paths resolve to the instrumented copies, and then using the PhantomJS file system APIs to create a colorized copy of the original js file to visually display coverage. We'll do a quick and dirty percentage coverage output to the console as well.


  1. Download JSCoverage 0.5.1
  2. Create a jscoverage.bat file in \jsunit with the following content
    @echo off
    C:\where\you\put\jscoverage\jscoverage.exe %*
    
  3. Create a template file for coverage information named coverageBase.htm in \jsunit
    • <!DOCTYPE html>
      <html>
      <head>
          <style>
              .code {
                  white-space: pre;
                  font-family: courier new;
                  width: 100%;            
              }
              
              .miss {
                  background-color: #FF0000;
              }
              
              .hit {
                  background-color: #94FF7C;
              }
              
              .undef {
                  background-color: #AFFF9E;
              }        
          </style>
      </head>
      <body>
      
      COLORIZED_LINE_HTML
      
      </body>
      </html>
      
  4. Update build.xml to perform a few new steps
    1. Create a \target\testjs\js directory and copy our js files into it
    2. Index our js files for code coverage, putting the indexed version into \target\testjs\jsinstrumented
    3. Copy *.test.htm into \target\testhtm
    4. Copy base resources to run tests (run-qunit.js, qunit.js, qunit.css) into \target\testhtm
    5. Copy the instrumented js files into \target\testhtm
      1. Note that because we used relative paths to our test js files the *.test.htm QUnit html files will now resolve js to the instrumented version when we run the files out of \target\testhtm
    6. Run PhantomJS on *.test.htm in \target\testhtm
    7. The updated build.xml looks like this:
    8. <?xml version="1.0" encoding="UTF-8"?>
      <project name="jsunittests" basedir="." default="main">
      	<property name="builddir" location="${basedir}/target"/>
      	<property name="jstestdir" location="${builddir}/testjs"/>
      	<property name="jsdir" location="${jstestdir}/js"/>
      	<property name="jsinstrumenteddir" location="${jstestdir}/jsinstrumented"/>
      	<property name="testhtmdir" location="${builddir}/testhtm"/>
      	
      	<condition property="phantom.filename" value="phantomjs.bat"><os family="windows"/></condition>
      	<condition property="phantom.filename" value="phantomjs.sh"><os family="unix"/></condition>   
      	
      	<property name="jscoverage.filename" value="jscoverage.bat" />
      	
      	<target name="clean">
      		<delete dir="${builddir}"/>
      	</target>
      	
      	<target name="prep">
      		<mkdir dir="${jsdir}"/>
      		<mkdir dir="${jsinstrumenteddir}"/>		
      		<mkdir dir="${testhtmdir}"/>
      		
      		<!-- copy non-test js files to target so we can mess with 'em. how we select which files may vary; for this 
      			 example just pick the one file we are testing.-->
      		<copy todir="${jsdir}">
      			<fileset dir="${basedir}">
      				<include name="testme.js" />
      			</fileset>
      		</copy>
      				
      		<!-- run jscoverage to produce a version of the file instrumented for code coverage -->
      		<exec executable="${jscoverage.filename}" failonerror="true">
      			<arg value="${jsdir}"/>
      			<arg value="${jsinstrumenteddir}"/>
      		</exec>   		
      		
      		<!-- copy our test htm files and modify them to point to the coverage indexed version of the test file. -->
      		<copy todir="${testhtmdir}">
      			<fileset dir="${basedir}">
      				<include name="**/*.test.htm" />
      			</fileset>
      		</copy>		
      		
      		<!-- copy core resources to testhtmdir so we can load them with same paths as when executing test htm files directly -->
      		<copy todir="${testhtmdir}">
      			<fileset dir="${jsinstrumenteddir}">
      				<include name="**/*.js" />
      				<exclude name="jscoverage.js"/>
      			</fileset>
      		</copy>				
      		<copy todir="${testhtmdir}">
      			<fileset dir="${basedir}">
      				<include name="test-support.js" />
      				<include name="run-qunit.js" />
      				<include name="qunit.css" />
      				<include name="qunit.js" />
      			</fileset>
      		</copy>				
      	</target>
      	
      	<target name="jstest">
            <!--Run all tests w/phantom, fail if tests fail. Execute all files w/extension .test.htm. -->
            <apply executable="${basedir}/${phantom.filename}" failonerror="true" dir="${testhtmdir}" relative="false">
               <arg value="run-qunit.js"/>
      		 <srcfile/>
      		 <arg value="${basedir}"/>
               <fileset dir="${testhtmdir}">
                  <include name="**/*.test.htm" />
               </fileset>
            </apply>			
      	</target>
      	
      	<target name="main" depends="clean, prep, jstest">
      	</target>
      </project>
      
  5. Modify our test-support.js to look for jscoverage data and output a rough count of lines hit, missed, and irrelevant (non-executable). Also expose a function a caller outside of page context can use to access coverage information. The new version should look like this:
    • //create a scope so we don't pollute global
      (function() {  
         var testName;
         
         //arg: { name }
      	QUnit.testStart = function(t) {
      	    testName = t.name;
      	};
      	
      	//arg: { name, failed, passed, total }
      	QUnit.testDone = function(t) {
      	    console.log('Test "' + t.name + '" completed: ' + (0 === t.failed ? 'pass' : 'FAIL'))
      	};
      	
      	//{ result, actual, expected, message }
      	QUnit.log = function(t) {
      	    if (!t.result) {
      	        console.log('Test "' + testName + '" assertion failed. Expected <' + t.expected + '> Actual <' + t.actual + '>' + (t.message ? ': \'' + t.message + '\'' : ''));
      	    }
      	};
      	
      	//we want this at global scope so outside callers can find it. In a more realistic implementation we
      	//should probably put it in a namespace.
      	window.getCoverageByLine = function() {
      		var key = null;
              var lines = null;
              //look for code coverage data    
              if (typeof _$jscoverage === 'object') {
      			for (key in _$jscoverage) {}
      			lines = _$jscoverage[key];
              } 
      
      		if (!lines) {
                 console.log('code coverage data is NOT available');
              } 
              		
              return { 'key': key, 'lines': lines };
         };
      
         QUnit.done = function(t) {
              var cvgInfo = getCoverageByLine();
              if (!!cvgInfo.lines) {
                  var testableLines = 0;
                  var testedLines = 0;
      			var untestableLines = 0;
                  for (lineIdx in cvgInfo.lines) {
      				var cvg = cvgInfo.lines[lineIdx];
      				if (typeof cvg === 'number') {
      					testableLines += 1;
      					if (cvg > 0) {
      						testedLines += 1;
      					}					
      				} else {
      					untestableLines += 1;
      				}
                  }     
                  var coverage = '' + Math.floor(100 * testedLines / testableLines) + '%';
                  
      			var result = document.getElementById('qunit-testresult');
      			if (result != null) {
      				result.innerHTML = result.innerHTML + ' ' + coverage + ' test coverage of ' + cvgInfo.key;
      			} else {
      				console.log('can\'t find test-result element to update');
      			}			
              }
         };  	
      }());
      
  6. Finally, modify run-qunit.js to load the original js file and produce a colorized version based on the coverage data we get by running the test against the version of the js file indexed for coverage. The new version should look like this:
    • /**
       * Wait until the test condition is true or a timeout occurs. Useful for waiting
       * on a server response or for a ui change (fadeIn, etc.) to occur.
       *
       * @param testFx javascript condition that evaluates to a boolean,
       * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
       * as a callback function.
       * @param onReady what to do when testFx condition is fulfilled,
       * it can be passed in as a string (e.g.: "1 == 1" or "$('#bar').is(':visible')" or
       * as a callback function.
       * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
       */
      function waitFor(testFx, onReady, timeOutMillis) {
          var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3001, //< Default Max Timout is 3s
              start = new Date().getTime(),
              condition = false,
              interval = setInterval(function() {
                  if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
                      // If not time-out yet and condition not yet fulfilled
                      condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
                  } else {
                      if(!condition) {
                          // If condition still not fulfilled (timeout but condition is 'false')
                          console.log("'waitFor()' timeout");
                          phantom.exit(1);
                      } else {
                          // Condition fulfilled (timeout and/or condition is 'true')
                          console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
                          typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
                          clearInterval(interval); //< Stop this interval
                      }
                  }
              }, 100); //< repeat check every 250ms
      };
      
      
      if (phantom.args.length === 0 || phantom.args.length > 3) {
          console.log('Usage: run-qunit.js URL basedir');
          phantom.exit(1);
      }
      
      var fs = require('fs');
      var page = require('webpage').create();
      
      // Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
      page.onConsoleMessage = function(msg) {
          console.log(msg);
      };
      
      var openPath = phantom.args[0].replace(/^.*(\\|\/)/, '');
      var basedir = phantom.args[1];
      var coverageBase = fs.read(basedir + fs.separator + 'coverageBase.htm');
      
      page.open(openPath, function(status){
          if (status !== "success") {
              console.log("Unable to access network");
              phantom.exit(1);
          } else {
              waitFor(function(){
                  return page.evaluate(function(){
                      var el = document.getElementById('qunit-testresult');
                      if (el && el.innerText.match('completed')) {
                          return true;
                      }
                      return false;
                  });
              }, function(){
      			//BEGIN MODIFIED: output colorized code coverage
      			//reach into page context and pull out coverage info. stringify to pass context boundaries.
      			var coverageInfo = JSON.parse(page.evaluate(function() { return JSON.stringify(getCoverageByLine()); }));
      			var lineCoverage = coverageInfo.lines;
      			var originalFile = basedir + fs.separator + coverageInfo.key;
      			var fileLines = readFileLines(originalFile);
      			
                  var colorized = '';
                  
      			console.log('lines=' + JSON.stringify(lineCoverage));
                  for (var idx=0; idx < lineCoverage.length; idx++) { 
                      //+1: coverage lines count from 1.
                      var cvg = lineCoverage[idx + 1];
                      var hitmiss = '';
                      if (typeof cvg === 'number') {
                          hitmiss = ' ' + (cvg>0 ? 'hit' : 'miss');
                      } else {
                          hitmiss = ' ' + 'undef';
                      }
                      var htmlLine = fileLines[idx].replace('<', '&lt;').replace('>', '&gt;');
                      colorized += '<div class="code' + hitmiss + '">' + htmlLine + '</div>\n';
                  };        
                  colorized = coverageBase.replace('COLORIZED_LINE_HTML', colorized);
                  
                  var coverageOutputFile = phantom.args[0].replace('.test.htm', '.coverage.htm');
                  fs.write(coverageOutputFile, colorized, 'w');
                  
                  console.log('Coverage for ' + coverageInfo.key + ' in ' + coverageOutputFile);			
      			//END MODIFIED
      		
                  var failedNum = page.evaluate(function(){
                      var el = document.getElementById('qunit-testresult');
                      console.log(el.innerText);
                      try {
                          return el.getElementsByClassName('failed')[0].innerHTML;
                      } catch (e) { }
                      return 10000;
                  });
                  phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0);
              });
          }
      });
      
      //MODIFIED: add new fn
      function readFileLines(filename) {
          var stream = fs.open(filename, 'r');
          var lines = [];
          var line;
          while (!stream.atEnd()) {
              lines.push(stream.readLine());
          }
          stream.close();
          
          return lines;
      }  
      
      
  7. Run 'ant'; you should see output similar to:

  8. Open \jsunit\target\testhtm\testme.test.htm in a browser; you should see something similar to this (note coverage % appears):

  9. Open \jsunit\target\testhtm\testme.coverage.htm in a browser; you should see something similar to this (red for untested, green for tested, light green for non-executable lines):

So where does that leave us?
We have clearly displayed we can accomplish some important things:


  • Write unit tests for Javascript
  • Run unit tests for Javascript in a command line build
  • Index Javascript files for code coverage
  • Output coverage percentage to the test runner (QUnit html file)
  • Render a colorized version of the Javascript under test clearly indicating which lines are/aren't being tested
I think this is awesome! Bear in mind in a real version we would of course make numerous refinements to this rather basic implementation; what we have is a proof of concept not by any stretch of the imagination an implementation ready for a team to consume.

117 comments:

Jackie Bolinsky said...

Hi there, I’m not a CI user, but I thought I’d sign up and tell you that the problem is actually with Doctrine cli not correctly passing the configuration to the generatemodelsdb task.
JavaScript Countdown Timer

Anonymous said...

have you ever tried writing the add function like this:

function add() {
var sum = 0;
for(var i in arguments){
sum += arguments[i];
}
return sum;
}

The test fails when I run it from the CL. In the browser the test is OK.

Superbowl2012 said...

Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.
SEO tools

Eric said...

Check this out, it adds sweet colors to the pass/fail output. Totally ganked it from https://gist.github.com/1588423, but it's still nice.

/*global QUnit */

//create a scope so we don't pollute global
(function(QUnit) {
var testName
, displayPass = '\033[1;92mPass\033[0m'
, displayFail = '\033[1;31mFail\033[0m';

//arg: { name }
QUnit.testStart = function(t) {
testName = t.name;
};

//arg: { name, failed, passed, total }
QUnit.testDone = function(t) {
console.log((0 === t.failed ? displayPass : displayFail) + ': ' + t.name);
};

//{ result, actual, expected, message }
QUnit.log = function(t) {
if (!t.result) {
console.log(' ' + testName + ' assertion failed. Expected <' + t.expected +
'> Actual <' + t.actual + '>' + (t.message ? ': \'' + t.message + '\'' : ''));
}
};
}(QUnit));

Eric said...

Actually, this too. You want it to handle .equal and .ok both, I think:

/*global QUnit */

//create a scope so we don't pollute global
(function(QUnit) {
var testName
, displayPass = '\033[1;92mPass\033[0m'
, displayFail = '\033[1;31mFail\033[0m';

//arg: { name }
QUnit.testStart = function(t) {
testName = t.name;
};

//arg: { name, failed, passed, total }
QUnit.testDone = function(t) {
console.log((0 === t.failed ? displayPass : displayFail) + ': ' + t.name);
};

//{ result, actual, expected, message }
QUnit.log = function(t) {
if (!t.result) {
if (t.expected) {//Only print this if it's there (works for 'equal' assertions)
console.log (' ' + 'Expected "' + t.expected + '" Actual "' + t.actual + '"');
}
console.log( ' ' + testName + ' assertion failed: ' + (t.message ? t.message : ''));
}
};
}(QUnit));

http://www.simpleascouldbe.com

Eric said...

Great instructions, thank you.

I ended up getting this to work in a way that is fairly elegant for our multi-platform maven system. I followed your instructions, with these enhancements to promote automation:

* I put installs of phantom-win and phantom-osx in the source tree so that run scripts could always depend on their location.
* I used maven-exec-plugin to run the .bat or .sh file, depending on the environment (developer needs to manually set the path to the batch file in ~/.m2/settings.xml, but that's a one time thing). This is attached to the integration-test phase.

This makes it so that after SCM update, the developer only needs to change the path to the executable in order for this to be automated.

http://www.simpleascouldbe.com

Interesting facts said...

Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again.
html5 music player| html5 media player

navya said...

I have read your blog its very attractive and impressive. I like it your blog.

Java Online Training Java EE Online Training Java EE Online Training Java 8 online training Core Java 8 online training

Java Online Training from India Java Online Training from India Core Java Training Online Core Java Training Online Java Training InstitutesJava Training Institutes

Anonymous said...

Nice blog..! I really loved reading through this article. Thanks for sharing such a
amazing post with us and keep blogging... iot training in chennai | iot training in chennai quora | iot training and placement in chennai | iot training center in chennai | best iot training centre in chennai

Anonymous said...

Great Blog Easy to understand lot of Things.
Really useful for Web Developers. Wordpress development company in chennai

ecommerce website development services

Best web design company in chennai

ecommerce website design services

Zinavo-Web Design | Web Development | SEO | Mobile Apps | ERP/CRM said...

Nice post. Thanks for sharing information about your services. This is really useful. Web Design & Development Company in Bangalore | Website Design Company in Bangalore | Web Designing Company in Bangalore | Web Design Companies in Bangalore

Vistas AD Media said...

Thanks for one marvelous posting! I enjoyed reading it; you are a great author. Vistas Ads Media provides
Web Design Company in Bangalore | Web Development Company in Bangalore | Advertising Agencies in Bangalore | SEO Company in Bangalore | Digital Marketing Companies in Bangalore | Ecommerce Website Development in Bangalore

adhi said...

awesome blog it's very nice and useful i got many more information it's really nice i like your blog styleweb design company in velacheryweb design company in chennai

Samuel Alex said...

Thanks so much for sharing this awesome info! I am looking forward to see more posts by you! Check out our websites,


Antivirus || Clean my PC || Antivirus Software || Antivirus Cleaner || Internet Security || Antivirus Protection || Internet Security Software || Antivirus Download || Security Antivirus || Antivirus and Security Software || Install Antivirus || Antivirus & Security Software || Mobile Security and Antivirus ||

Asif Sarkar said...

Wonderful Blog, It is really helpful for users. thanks for sharing. seo services in kolkata | seo company in kolkata | seo service provider in kolkata | seo companies in kolkata | seo expert in kolkata | seo service in kolkata | seo company in india | best seo services in kolkata | digital marketing company in kolkata | website design company in kolkata

Brandstory said...

Nice post Really useful information  Web Design Company in Bangalore, Web Development Company in Bangalore, Web Design Services in Bangalore, Web Design Company in Bangalore, Best Website Design Companies in Bangalore, Best Website Development Company in Bangalore, Website Design Services in Bangalore, Best Website Design Company in Bangalore, SEO Company in Bangalore, SEO Agency in Bangalore, SEO Services in Bangalore, Best SEO Companies in Bangalore, SEO Services Company in Bangalore

Anonymous said...

Nice Blog!! Thanks For Sharing Wonderful Post.
Digital Marketing | Outsource SEO Services | Digital Marketing Services | Digital Marketing in India | Facebook Ads | Lead Generation Services

Rahul said...

Nice Article..Thanks for the information..found ir really interesting

Python Training in Chennai
Python Training Institute in Chennai
Python Training in Chennai Anna Nagar
Python Training in Chennai OMR
UiPath Training in Chennai
Informatica Training in Chennai
Informatica Training Center Chennai
Informatica Training Center in Chennai

Desinelabs said...

Thanks for the information...

seo services bangalore

Desinelabs said...

Thanks for sharing your info. I really appreciate your efforts and I will be waiting for your further write ups thanks once again...
Digital Marketing Company in Bangalore
Digital Marketing Agencies in Bangalore

Imcrinox said...
This comment has been removed by the author.
YorviTech said...

Learning basics being a Developer is very necessary. Thanks for sharing this article, share more in future.

Anurag Srivastava said...

Hey, Your post is very informative and helpful for us...Postal Recruitment 2020 is a leading job website for all Government job recruitment notification. This page is an exclusive page for the Latest recruitment notification from India Post India Post 2020...

My Digital Leader said...

Good one. Thanks for sharing
Digital Marketing company in Bangalore l Web Design Company in Bangalore l Web Development Company in Bangalore l Advertising Agencies in Bangalore l SEO Company in Bangalore l SEO Company in Bangalore l Digital Marketing Companies in Bangalore l Ecommerce Website Development in Bangalore

Techiesys said...

Good content seo company in Bangalore

Techiesys said...

Amazing information shared.

SEO agency in Bangalore

Pooja said...

To Know FreeJobAlert and to know more about upcoming jobs .

Quikks Digital Solutions said...

Good Technical Blog.Are you looking to revamp or optimize your blog?
We are a Seo Firm Bangalore.Our Senior SEO Consultant have a 10+ years experience, offer services like
SEO,PPC,SMM,online reputation management & web development both to small and medium companies.As a running offer,we are providing free performance audit for our customers

SEO COMPANY KERALA said...

Hiring the digital marketing company in Cochin becomes necessary for businesses in Cochin to acquire their digital marketing needs. Even the interaction between the client and the digital marketing company is the source to curate an engaging social presence for a business site. By reading more this parchment, you can find how the businesses are benefited by interacting with the digital marketing agency.
digital marketing company in kochi
digital marketing agency in kochi
digital marketing company in kerala
digital marketing agency in kerala
digital marketing kochi
digital marketing company in cochin
digital marketing kerala

SEO COMPANY KERALA said...

The confidence you gather against the Company at the first meeting is the main evidence to extend your journey with them. Every business person will have the expectation level on their first meeting with the new clients. It is a common thing and it is the essential one for them to decide for invests in SEO services. Read more this article to find a genuine answer from the genuine SEO Company Kerala to take the business to the next level.

seo company kerala
seo services in kochi
seo services in cochin
seo kochi
seo services kochi
seo company ernakulam
seo agency kochi

swati singh said...

Thank you for sharing your information i like that your content and your writing way. keep sharing your content and also write a blog about the invest in startups. Keep posting!

Brandstory said...

Thanks for your post! Really interesting blogs. Here is the some more interesting and most related links.

Best digital marketing company in Dubai, United Arab Emirates. Brandstory is one of the top and best digital marketing companies in Dubai UAE. As a leading digital marketing agency in Dubai, We offer search engine optimization services, online marketing services, UI UX design services, search engine marketing services, email marketing services, Google / Facebook / Bing pay per click services, Internet marketing services, website design services and website development services, social media marketing services. Hire ROI based digital marketing services company in dubai to get digital leads for your business.

Digital marketing company in Dubai | Digital Marketing Agency in Dubai | SEO Company in Dubai | SEO Agency in Dubai | Best Digital Marketing Companies in Dubai | Top Digital Marketing Agencies in Dubai | Best SEO Companies in Dubai | SEO Agencies in Dubai | Online Marketing Company in Dubai | SEO Services Company in Dubai | PPC Company in Dubai | PPC Agency in Dubai | PPC Services in Dubai | Social Media Marketing Company in Dubai | Social Media Marketing Services in Dubai | Social Media Marketing Agencies in Dubai | Web Design Company in Dubai | Website Designers in Dubai | Website Development Services Company in Dubai | Web Design Companies in Dubai

హాట్‌గర్ల్స్ said...

It's Really A Great Post. Looking For Some More Stuff.

Digital marketing agency in hyderabad | Digital marketing

companies in hyderabad

హాట్‌గర్ల్స్ said...

Thanks for your post! Really interesting blogs.

Digital marketing company | Digital Marketing Agency | Digitaln Marketing Companies in Bangalore

హాట్‌గర్ల్స్ said...

he post was really very good.Thanks for sharing.

SEO company in bangalore | SEO services in

bangalore

Unknown said...


Very Useful blog. Thanks for sharing.

If anyone have to boost their website in google.please connect with the leading SEO Expert Kerala. Get an Afforadable SEO Services from the SEO Freelancer Kerala.

Unknown said...

SIAUAE is one of the top audit firms in UAE with highly experienced professionals. As a leading vat consultancy services in uae, we achieved the label of best VAT consultant in UAE.

Looking for the top accounting firms in UAE? SIAUAE is the best accounting companies in uae , we offer comprehensive professional services in UAE.

SIAUAE management consultancy is a professional Management Consultancy UAE , Helping clients achieve their business goals. For more details call us now

Unknown said...

Everybody want digital marketing company Kerala to have their organization on the highest point of the pursuit list and engage your business. We Provide Best Digital Services, Efficiently total start to finish center abilities without viable thoughts. Powerfully cultivate strategic arrangements without empowered worth. Interfacing your business to the clients who are keen on your administration, and make a chain of best digital marketing in Kochi.
digital marketing company Kerala

Unknown said...

Today the companies are continually being challenged to reduce the expenses, most of working expenditures and other requirements. The main costs include the salary of employees like HR professional, accountant, auditors and administration. These problem can be overcome by best expert business outsourcing company. They provide quality and valuable services at low cost for the business enterprises. In UAE most of accounts payable outsourcing companies offers cost effective accounting services that will help the companies effectively in the current situation.
Audit firms in UAE

Unknown said...

The intensity of smells can't be exaggerated. Smell has such a solid association with one's passionate express that it revives the recollections that went with our experience, in a few occasions, returning over numerous years. A deliberately built fragrance can lift one's state of mind, and places one out of a positive and innovative outlook. Our fragrance arrangements give you a chance to make the ideal experience for your customers and associates – one in which they remain drew in and associated.
Aroma diffuser

Unknown said...

Good Blog, thanks for sharing
everybody want digital marketing company Kerala to have their organization on the highest point of the pursuit list and engage your business. We Provide Best Digital Services, Efficiently total start to finish center abilities without viable thoughts. Powerfully cultivate strategic arrangements without empowered worth. Interfacing your business to the clients who are keen on your administration, and make a chain of best digital marketing in Kochi.
Digital marketing company Kerala

Unknown said...

Good Blog, thanks for sharing
the intensity of smells can't be exaggerated. Smell has such a solid association with one's passionate express that it revives the recollections that went with our experience, in a few occasions, returning over numerous years. A deliberately built fragrance can lift one's state of mind, and places one out of a positive and innovative outlook. Our fragrance arrangements give you a chance to make the ideal experience for your customers and associates – one in which they remain drew in and associated.
Aroma diffuser

Unknown said...

Good Blog, thanks for sharing
Today the companies are continually being challenged to reduce the expenses, most of working expenditures and other requirements. The main costs include the salary of employees like HR professional, accountant, auditors and administration. These problem can be overcome by best expert business outsourcing company. They provide quality and valuable services at low cost for the business enterprises. In UAE most of accounts payable outsourcing companies offers cost effective accounting services that will help the companies effectively in the current situation.
Audit firms in UAE

Online Training Courses said...

If you want to survive in the technology world, you have to learn python for data science. In order to gain knowledge, it is recommended to attend some training courses.

Online Training Courses said...

Dot net Information:

https://dotnetcourseonline.wordpress.com/
https://dotnetonlinetrainingcourse.blogspot.com/
https://sites.google.com/view/microsoft-certification-course/
https://netdevelopercourse.tumblr.com/
https://learndotnet.wixsite.com/learndotnet/

Online Training Courses said...

Data Science Online Training

https://datasciencecourse229747904.wordpress.com/
https://datasciencecourseinusa.blogspot.com/
https://sites.google.com/view/free-data-science-courses/
https://onlinetrainingusa.wixsite.com/datasciencecourses
https://bestdatasciencecourses.tumblr.com/

Online Training Courses said...

https://bestseleniumonlinetrainingcourse.wordpress.com/
https://automationtestingcoursesonline.blogspot.com/
https://sites.google.com/view/selenium-certification-online/
https://learnseleniumonline.wixsite.com/selenium/
https://bestsitetolearnselenium.tumblr.com/
https://seleniumwebdriverforbeginners.yolasite.com/

wwwnortoncomsetup.com said...

I found this is an informative blog and also very useful and knowledgeable. I would like to thank you for the efforts you have made in writing this blog norton.com/setup

activate-redeem.com said...

Great information, I was searching for this kind of information, thank you very much for sharing with us. i also have some links to share mcafee.com/activate

www.mcafee.com/activate

thenortonsetup.com said...

Very nice blog, I found it very useful .Even I have this wonderful website norton.com/setup
www.norton.com/setup

avg-retail.com said...

I'm so glad and enjoyed your BLOG, It is very informative on the subject or topic, and Thanks For Sharing this post. I have something to share here www.avg.com/retail

www.avg.com/activate

avg.com/activate

avg.com/retail

Norton Product Key said...

There are many blogs I have read But when I read Your Blogs I have found such useful information, fresh content with such a amazing editing everything is superb in your blog, Thank you so much for sharing this useful and informative information with us. Wish you all the best for upcoming comments. And I have also few informative links which I am going share here. wwww.norton.com/setup enter product key
www.norton.com/setup, Norton product key, Norton com setup download, norton.com/setup

john said...

Great Article Artificial Intelligence Projects

Project Center in Chennai

JavaScript Training in Chennai

JavaScript Training in Chennai

kseo.agency said...

ISO Certification in Delhi – Genveritas a global ISO Certification Consulting firm represents considerable authority in tweaked and result-situated answers for assisting organizations to actualize change and improve business execution.

Neuro Doctors are a cohesive group of Top Neurosurgeon in Bangalore Neurologists, Intervention Neuroradiologist, pain management specialists who work together to provide comprehensive neurosciences care to our patients.

KEEN SEO Agency – Best Web Design Company in Bangalore . We provide full-service Web Design & Development Solutions that also includes specialized SEO services for Small Businesses. We offer Strategist Local SEO, Ecommerce SEO, website auditing, Paid Search (PPC) strategies including Google Ads, Facebook & Linked In Ads for Small Business (B2B & B2C).

John said...

Great article shared.Web Development company Kochi

Imcrinox said...
This comment has been removed by the author.
Content Writer said...

Thanks for your great post we are the leading digital marketing companies in Bangalore and seo companies in Bangalore 

DigiRoads said...


HI guys,
This is a very good post, and I like it very much. For us, it's insightful and helpful. For a long time, I've been looking for this and I'm just really pleased to say that I'm working with this stuff as well. Thanks for sharing this with us.
Digital Marketing Company in Jaipur
Digital Marketing Company In Bangalore
seo company In Delhi

Best Agriculture Financial Company in India said...

great blog. Really love your content do check Agricultural Investment Company

Best Agriculture Financial Company in India

Sage 50 and QuickBooks Support said...

Well done! Great article...
QuickBooks Error 3371 status code 11104
Sage 50 keeps asking to update
QuickBooks unable to complete this operations and needs to restart
Cannot connect to Sage 50 database on network
Proforma invoice QuickBooks
Sage 50 import and upload exiting data
How to transfer Sage 50 files to another computer
Find missing QuickBooks 2019 license and product number
Reached to maximum allowed connection to Sage 50
Sage will not accept correct password

Aadi Web Solutions said...


Aadi Web Solutions Is a well-established website designing company in Faridabad with 8 years of solid experience.website designing. Every Web design & development needs a different approach to build that’s why we have experts of every kind. We are flexible, versatile, and the pro at it. Our experts are working on CMS that is multi-functional, scalable, and dynamic in web development by utilizing the high end technologies like ASP.Net/PHP. We develop websites for small and Enterprise level business. We are best Web Designing Company In Faridabad If you want to propel your business forward.

divvidivya said...

Nice Blog. For all Best Digital Marketing Services In Hyderabad visit 9and9.

Anonymous said...

Best Digital Marketing Company in Hyderabad- 9and9 DigiSoft Insights Private Limited
9and9 DigiSoft is a leading and Top Digital Marketing Agency in Hyderabad focused on empowering and influence Brands through SEO, SEM, Social Media and Email marketing
https://9and9.com/
9912891000
contact@9and9.com

fuel digital vignesh said...

We are the Best Digital Marketing Agency in Chennai,Coimbatore,Madurai and change makers of digital! For Enquiry Contact us @+91 9791811111
digital marketing agencies in chennai
seo service in chennai
website designers in chennai
Best SMO services in Chennai
Best content marketers in Chennai
best logo makers in chennai
google adwords service in chennai

www.webhealthmart.com said...

Nice post, you give the clear idea of the topic and I subscribed your blog, I have some links to share here

Buy Ambien Online

Order Ambien Online

Buy Ambien 10mg Online



xanax bars for sale


fastest Modafinil delivery


ativan 2mg buy online


ativan 1mg tablet buy online

DigiRoads said...

HI guys,
This is a very good post, and I like it very much. For us, it's insightful and helpful. For a long time, I've been looking for this and I'm just really pleased to say that I'm working with this stuff as well. Thanks for sharing this with us.
Digital Marketing Company in Jaipur
Digital Marketing Company In Bangalore
Digital Marketing company In Delhi

mani said...

I really like reading through a post that can make people think. Also, many thanks for permitting me to comment!

Best SEO Company in Bangalore|
SEO Services Company In Bangalore|
SEO Services In Bangalore|
Mobile App Development Companies In Bangalore|
Best Mobile App Development Companies In Bangalore|

Unknown said...

Thanks for sharing this useful Blog. For all Digital Marketing Services In Hyderabad visit 9and9.

Mahalakshmi said...

Nice post really useful information. We are the leading website development company in dubai. Hire our web design company in dubai today for web design services in dubai

Brandstory Cambridge said...

Nice post really useful information. We are the leading seo agency in dubai. Hire our seo company in dubai today for seo services in dubai

Abishek said...

Nice post it is really an interesting article.We are also providing the web design services in mumbai. We are the leading
website development company in mumbai
web design company in mumbai

Keerthi said...

Thanks for your great posts.We are the leading seo company in mumbai. Hire our seo agency in mumbai today for seo services in mumbai

Gorish dua said...

Thanks for sharing.
We at Antino Labs believe in redefining and refining our model to suit the industry's requirements. Antino Labs' several years of experience in the market has let us register our global presence. Antino Labs' has the vision to become the world's most trusted partner for digital transformation and we aim to become a brand that defines innovation and the latest technology. We offer clients a one-stop solution for all their interests regarding IT consulting services in Gurgaon and UI/UX design services in Gurgaon.

ISO 9001 Certification in South Africa said...

hello very nice blog. it is really an interesting article we are providing some backlinks. I hope these content useful for you.
backlinks
backlinks
backlinks
backlinks
backlinks
backlinks
backlinks
backlinks

ISO Implementation in Saudi Arabia said...

Hi this do follow backlink this has a amazing content, thanks for sharing
Do Backlinks
Do Backlinks
Do Backlinks

ISO Consultant in Singapore said...

Hi, thanks for sharing this amazing content.
Backlinks
Backlinks
Backlinks
Backlinks

ISO Consultant in Singapore said...

Great article with fantastic notion I admire your submit thankyou so lots and let preserve on sharing your stuff
Backlinks
Backlinks
Backlinks
Backlinks

ISO 9001 Certification in South Africa said...

hello every one nice blog. it is really an interesting article here providing some backlinks.
backlinks
backlinks
backlinks
backlinks
backlinks
backlinks

ISO Consultant in Singapore said...

Hello everyone this information is very useful for us. We are Hoping that you will continue posting such an useful backlinks having valid information
Backlinks
Backlinks

ISO Consultant in Singapore said...

Hello everyone These are the top Digital Marketing organizing organizations in Dubai business viability with effective development and arrangement.
Backlinks
Backlinks
Backlinks
Backlinks

ISO 9001 Certification in South Africa said...

hello every one nice blog. it is really an interesting article We are also providing some backlinks.
backlinks
backlinks
backlinks
backlinks
backlinks
backlinks

ISO Consultant in Singapore said...

Hi everyone Thanks for your post! Really fascinating blogs. Here is the some greater fascinating and most associated links.
Backlinks
Backlinks

ISO Implementation in Saudi Arabia said...

Hi Thanks for sharing this fabulous content
Do Backlinks
Do Backlinks
Do Backlinks

Brandstory Cambridge said...

Nice post really useful information. We are the leading Ecommerce Website Development in Bangalore . Hire our ecommerce website development in bangalore for ecommerce website development services.

Anonymous said...

very informative article about "integrating javascripts" found it very useful...

B2B Appointment Setting Services

Architectural CAD Drafting said...


HTML pages are usually integrated with JavaScript functions. ... JavaScript is the main scripting language used to make web pages dynamic, very informative article about "javascript"

Architectural CAD services

ISO Consultant in Singapore said...

Hello, your blog is greater informational for me thanks for sharing such kind of content material really. It is a very beneficial and information helpful content material like us.
Backlinks
Backlinks

ISO 9001 Certification in South Africa said...

Very Nice post it is really an interesting article. this informative backlink
backlinks
backlinks
backlinks
backlinks
backlinks
backlinks

Anonymous said...

thanks for sharing very informative post about "integrating javascript tests"

Outsourced Lead Generation Services

Architectural CAD Drafting said...

must appreciate very informative post about "integrating java scripts"

BIM service providers

ppc fame said...

As one of the leading Web designing company in Mohali, we cater to the fraternity of the clients and provide them the services which suits best to their requirements. We analyze the situation of every business deeply, understand their purpose and comprehend with it accordingly. Our services include web designing, Logo Design, web development and search engine optimization. We provide websites to our clients which are very cost efficiently. We work in all the industries from fashion to Entertainment to health care and real estate. When it comes to your business you should not take chances but rather go for the best and we at PPC Fame provide you with the best resolutions. We are the first preference for the industry leaders and well settled businesses when it comes to best Web development company in Mohali.
Web designing company in Mohali

Aakarist said...

What a wonderful blog! Thanks for this information, it's quite useful. Aakarist is the best graphic designing company, digital marketing company, mobile app development company, ui ux designing company, social media marketing agency, Best seo services company and website designing company in india.

ISO 9001 Certification in South Africa said...

Hello Everyone! Great article! This is very necessary archives for us. I like all content material fabric and information. I have observe it. You recognize more about this please go to again
backlinks
backlinks
backlinks
backlinks
backlinks

Cre8tivebot said...

Good Job! You have Shared your well knowledge... I will refer the people to the best IT Solutions providers click the below link:

IT Company
seo packages
ppc company australia
content marketing agency dubai
social media marketing company
web development australia
app development melbourne

cityweb said...

Great blog.Thanks for sharing such a useful information
best seo company in bangalore

best seo services company in bangalore

G-sol said...
This comment has been removed by the author.
G-sol said...

Certified Digital Marketing course in Panchkula

G-sol said...

Digital Marketing Training Institute in Panchkula

Mona Mishra said...

Nice blog on JAVA.
Ecommerce development Company

Mona Mishra said...

nice post on java script .
We are helping eCommerce businesses by increasing their customer reach and growing revenue through the optimal combination tools, and user-centric solutions. Being India’s leading eCommerce software development company, we help B2B & B2C clients drive their customers’ satisfaction, expand their right potential audiences and boost sales upto 100%.
Ecommerce development Company

periyannan said...

Great explanation.. Thanks
Internship providing companies in chennai | Where to do internship | internship opportunities in Chennai | internship offer letter | What internship should i do | How internship works | how many internships should i do ? | internship and inplant training difference | internship guidelines for students | why internship is necessary

Village Talkies said...

A great blog, it has a lot of useful information to me
Village Talkies a top-quality professional corporate video production company in Bangalore and also best explainer video company in Bangalore & animation video makers in Bangalore, Chennai, India & Maryland, Baltimore, USA provides Corporate & Brand films, Promotional, Marketing videos & Training videos, Product demo videos, Employee videos, Product video explainers, eLearning videos, 2d Animation, 3d Animation, Motion Graphics, Whiteboard Explainer videos Client Testimonial Videos, Video Presentation and more for all start-ups, industries, and corporate companies. From scripting to corporate video production services, explainer & 3d, 2d animation video production , our solutions are customized to your budget, timeline, and to meet the company goals and objectives.
As a best video production company in Bangalore, we produce quality and creative videos to our clients.

orient tech said...

Welcome to Orient Tech
Orienttech W.L.L. is a well established and fast growing trading companies in the country of Qatar and Bahrain . Our line of business involves wholesale and Retail supply of Automotive spares, Racking and Shelving products.

Gratis School of Learning said...

Deal All, Are you looking IELTS exam preparation guidelines?? We provide Free IELTS Workshop in Panchkula.

Call today: +91 9887046666

WordPar said...

WordPar International is a quality-conscious translation agency offering linguistic services for a wide range of industry requirements.
WordPar provides professional language services with the help of a world-wide network of professional translators and linguists. All language specialists are native speakers of the respective target languages.
Our services include translation, interpretation, voiceover, subtitling and transcription among others. Projects are executed with meticulous care and close attention to terminology, correctness of language and other relevant aspects of the deliverables.

diksha said...

rotavator price

rotavator price

top computer coaching said...

If you are looking for the Digital marketing course in east delhi then, BIIT New Delhi is the best computer institute for you. It has highly professional faculties who will teach you professionally. For more information you can call us on 9311441524, Visit to address A-115 , First Floor , Near Panna Sweet, Shakarpur, Vikas Marg, Laxmi Nagar, Computer Institute, Opposite Metro Piller No. 33, Delhi, 110092, Mail us on biitnewdelhi@gmail.com or can also visit to our official site http://www.biitnewdelhi.com/.

Sarah Rob said...

Nice blog. Appreciate your thoughts. Ecommerce web development dubai

QB DATA SERVICE SUPPORT said...

QuickBooks Error the file exists issue user may encounter where the data is being saved in the company file But due to some malfunction error triggers and The reason for such issue is Damaged in the QuickBooks Program or the company file is damaged. Therefore we have shared some easiest way to fix Error file exists in QuickBooks and For moreover you can also contact to Data service team at 800-579-9430.

Meghana Sathish said...

Great blog, very informative blog on development tips. we are leading Graphic designing company in Bangalore.

nidhi pethe said...

Amazing article. It's very useful.
It looks like you have put lot of work into this.
SMARS designs jewelry to run along with your ever-changing wardrobe. A piece of Jewelry can either make or break your entire look; therefore, every unique outfit needs a different piece of jewelry to compliment it. But looking at the prices of traditional jewelry, we usually find occasions like festivals or ceremonies to buy it. And these adorable pieces spend most of their lives in the lockers. Komal, the founder of SMARS, understood this gap in the market. Every single piece is limited edition and walks hand-in-hand with trends. Adored by customers from all over the world, we ensure the quality delivery of our high-end, Indian fashion costume jewelry. Shop online for latest collection of Kundan, antique and temple jewelry in India check out necklace sets, earrings, bangles, chokers for girls and many more Indian jewelry sets for women available with free shipping across India.
Take a look: Bangles Set For Girls Online

Samuel Alex said...
This comment has been removed by the author.
TheBEGlobal said...

Thanks for Sharing. We are well-known as a Social Media Marketing Company in Dubai. We provide quality services and advertising and lead generation

BEGlobal(US)LLC said...

Thanks for Sharing. Are you searching for a Digital Marketing company in Michigan? Then BE Global LLC is the right place for you. We are specializing in SEO, PPC, Social Media Marketing, and more.

구미뷰티테라피 said...

very much for sharing this article. It helped me a lot and made me feel a lot. Please feel free to share such사천출장아로마
양산출장아로마
진주출장아로마
창원출장아로마
통영출장아로마

Martin said...

We are a search engine optimization company in Dubai, UAE. SEO Services in Dubai We offer our best SEO services to businesses looking to rank higher on Google and get the attention they deserve

BEdigitech said...

Thanks for sharing. Bedigitech presenting SEO Services in India. As a result, our clients have achieved good search engine rankings with high-quality traffic.

Post a Comment