How to create test suite in JsUnit - jsunit

How do I create a test suite in JsUnit like I would with JUnit? I have many tests that I would like to run together. For example, I have two tests in test1.html and test2.html that I would like to group together to run.

Write a suite function in your page that returns a JsUnitTestSuite.
function suite(){
var suite = new JsUnitTestSuite();
suite.addTestPage("/path/test1.html");//use the addTestPage() method to add a test page
suite.addTestPage("/path/test2.html");
return suite;
}

Related

How can i use Faker.js to generate random data for protractor test cases.?

I would like to generate random input for protractor using faker.js. Please provide a way for using faker.js with protractor.
Should be simple. Just generate random data in Conf.js and refer them in your tests
onPrepare: function() {
var Faker = require('./Faker');
browser.params.randomName = Faker.Name.findName(); // Rowan Nikolaus
browser.params.randomEmail = Faker.Internet.email(); // Kassandra.Haley#erich.biz
},
And in your tests just use these dynamically generated data
element(By.css('.blahblah')).sendKeys(browser.params.randomName)
For more details refer my blog # Using FakerJs in Protractor

Run the same suite 2 times with different params

Is there way to merge 2 commands into 1 command
protractor protractor.conf --suite create_buyer --params.buyerName=Buyer1
protractor protractor.conf --suite create_buyer --params.buyerName=Buyer2
like
protractor protractor.conf --suite create_buyer,create_buyer --params.suites[0].buyerName=Buyer1 --params.suites[1].buyerName=Buyer2
to make this commad work i need to know the current suite index
is it possible?
may there is better way!
As far as i know, there is no way you can do it using Protractor. However, if you want to run the same suite twice, then there is a better way of handling this situation using data-providers. There are many ways to create a data driven framework for protractor, but the easiest one that i feel is using jasmine-data-provider, which is an npm package. Here's how you can do it -
Update conf.js file to include the suite and params -
suites: {
create_buyer: ['./firstSpec.js'] //All your specs
},
params: {
buyerName1: '',
buyerName2: ''
},
Update all test scripts file to include the dataprovider -
//Require the dataprovider
var dp = require('/PATH_TO/node_modules/jasmine-data-provider'); //Update your path where the jasmine-data-provider is installed
//Usage of dataprovider in your specs
var objectDataProvider = {
'Test1': {buyerName: browser.params.buyerName1},
'Test2': {buyerName: browser.params.buyerName2}
};
dp(objectDataProvider, function (data, description) {
//Whole describe or anything in the dp() runs twice
describe('First Suite Test: ', function(){
it('First Spec', function(){
element.sendKeys(data.buyerName); //usage of the data buyerNames
//Your code for the spec
});
//All your specs
});
});
Now pass in the parameters using command prompt -
protractor protractor.conf --suite create_buyer --params.buyerName1=Buyer1 --params.buyerName2=Buyer2
NOTE: However the issue here is that you cannot run one single suite at a single stretch with one buyerName. For ex: You cannot run all specs in the suite create_buyer at one stretch using buyerName1. Instead, one spec will run twice serially, once with buyerName1 and buyerName2, then it continues to next spec. But i guess, that should also work if your requirement is to not use a strict flow for one buyer (i.e, to complete end-to-end testing of suite create_buyer with buyerName1 and then run suite create_buyer with buyerName2 - this shouldn't be the case as the thumb rule of automation says that one test script shouldn't depend on another).
Hope it helps

Code coverage for Protractor tests in AngularJS

I am running some e2e tests in my angularJS app with protractor (as recommended in the angularJS documentation).
I've googled around and cannot find any information on how to measure coverage for my protractor tests.
I think I'm missing something here... is there any way to get a code coverage report for protractor e2e tests? Or is it simply a feature for unit tests?
This is achievable using Istanbul. Here is the process, with some example configurations that I've extracted from our project (not tested):
Instrument your code using the command istanbul instrument. Make sure that istanbul's coverage variable is __coverage__.
// gulpfile.js
gulp.task('concat', function () {
gulp.src(PATH.src)
// Instrument for protractor-istanbul-plugin:
.pipe(istanbul({coverageVariable: '__coverage__'}))
.pipe(concat('scripts.js'))
.pipe(gulp.dest(PATH.dest))
});
Configure Protractor with the plugin protractor-istanbul-plugin.
// spec-e2e.conf.js
var istanbulPlugin = require('protractor-istanbul-plugin');
exports.config = {
// [...]
plugins: [{ inline: istanbulPlugin }]
};
Run your tests.
Extract the reports using istanbul report.
This approach has worked for me and is easy to combine with coverage reports from unit tests as well. To automate, I've put step 1 into my gulpfile.js and step 3 and 4 in the test and posttest scripts in package.json, more or less like this:
// In package.json:
"scripts": {
"test": "gulp concat && protractor tests/spec-e2e.conf.js",
"posttest": "istanbul report --include coverage/**/.json --dir reports/coverage cobertura"
},
if you are using grunt - you can use grunt-protractor-coverage plugin, it will do the job for you. You will have to instrument the code first and then use the mentioned plugin to create coverage reports for you.
To add to ryanb's answer, I haven't tried this but you should be able to use something like gulp-istanbul to instrument the code and override the default coverage variable, then define an onComplete function on the jasmineNodeOpts object in your Protractor config file. It gets called once right before everything is closed down.
exports.config = {
// ...
jasmineNodeOpts: {
onComplete: function(){
browser.driver.executeScript("return __coverage__;").then(function(val) {
fs.writeFileSync("/path/to/coverage.json", JSON.stringify(val));
});
}
}
};
I initially tried the onComplete method suggested by daniellmb, but getting the coverage results only at the end will not include all the results if there were multiple page loads during the tests. Here's a gist that sums up how I got things working, but basically I had to create a reporter that added coverage results to the instanbul collector every time a spec finished, and then wrote the reports in the onComplete method. I also had to use a "waitPlugin" as suggested by sjelin to prevent protractor from exiting before the results were written.
https://gist.github.com/jbarrus/286cee4294a6537e8217
I managed to get it working, but it's a hack at the moment. I use one of the existing grunt istanbul plugins to instrument the code. Then I made a dummy spec that grabs the 'coverage' global variable and write it to a file. After that, you can create a report with any of the reporting plugins.
The (very over-simplified) test looks like:
describe('Output the code coverage objects', function() {
it('should output the coverage object.', function() {
browser.driver.executeScript("return __coverage__;").then(function(val) {
fs.writeFileSync("/path/to/coverage.json", JSON.stringify(val));
});
});
});

angularjs e2e testing assertions with mock http

I currently run my angularjs testing environment using ngMockEE which, using a special testing module allows me to mock http responses as such;
var things = [thing01, thing02];
$httpBackend.whenGET('/v1/things?').respond(function() {return [200, things]});
In a separate file I define e2e tests which call a things.html file that includes that testing module.
I then define a e2e test like this;
browser().navigateTo('/test/thingTest.html');
expect(element('.table.things tbody tr').count()).toEqual(2);
Now, what would be nice is if I could somehow couple the two togther, so that I could write an assertion like this - avoiding hard coding that 2 which will need updating over time if I update my list of things
browser().navigateTo('/test/thingTest.html');
expect(element('.table.things tbody tr').count()).toEqual(things.length);
However I'm not quite sure if this is possible or advisable. Any thoughts?
Well, you could use an e2eData.js file containing those values, and which would be loaded both by your tests, and by the tested page:
In e2eData.js:
...
var e2eData = {
things : [thing01, thing02],
...
}
In your e2e module:
$httpBackend.whenGET('/v1/things?').respond(function() {return [200, e2eData.things]});
In your test:
expect(element('.table.things tbody tr').count()).toEqual(e2eData.things.length);

How do I provide re-usable sample data values to my angularjs / jasmine unit-tests

I would like to provide simple constant values such as names, emails, etc to use in my jasmine unit tests.
A similar question was asked here: AngularJS + Karma: reuse a mock service when unit testing directives or controllers
In c# I would create a static class to hold little snippets of mock data. I can then use these values throughout my unit tests, like this:
static class SampleData
{
public const string Guid = "0e3ae555-9fc7-4b89-9ea4-a8b63097c50a";
public const string Password = "3Qr}b7_N$yZ6";
public const string InvalidGuid = "[invalid-guid]";
public const string InvalidPassword = "[invalid-password]";
}
I would like to have the same convenience when testing my AngularJS app using Karma / Jasmine.
I know that I can define a constant object against my angular app, I already do this for constants I use in the real code, like this:
myApp.constant('config', {apiUrl:'http://localhost:8082'})
I could add another constant just like this but only containing sample data values for use in my unit tests, like this:
myApp.constant('sampleData', {email: 'sample#email.com'})
I could then just inject the mock constant object into my tests and off I go, like this
describe 'A sample unit test', ->
beforeEach -> module 'myApp'
beforeEach inject ($injector) ->
#sampleData = $injector.get 'sampleData'
email = #sampleData.email
# etc ...
However this seems a bit fishy to me. I don't want my production code to contain sample data that is only required by my unit-tests.
How would you conveniently provide your angular / jasmine unit tests with re-usable sample data values?
Thanks
There are two ways of doing this:
spy on function calls and return fake values.
create mock classes (and possibly mock data to initialise them) and load them wherever you need
The first one is alright when you only have to fake a few calls. doing that for a whole class is unsustainable.
For example, let's say you have a service that builds some special URLs. If one of the methods depends on absUrl, you can fake it by spying on the method in the $location object:
describe('example') function () {
beforeEach(inject(function () {
spyOn($location, 'absUrl').andCallFake(function (p) {
return 'http://localhost/app/index.html#/chickenurl';
});
}));
it('should return the url http://www.chicken.org') ... {
// starting situation
// run the function
// asserts
}
Now let's say that you have a Settings Service that encapsulates data like language, theme, special paths, background color, typeface... that is initialised using a remote call to a server.
Testing services that depend on Settings will be painful. You have to mock a big component with spyOn every time. If you have 10 services... you don't want to copypaste the spyOn functions in all of them.
ServiceA uses Settings service:
describe('ServiceA', function () {
var settings, serviceA;
beforeEach(module('myapp.mocks.settings')); // mock settings
beforeEach(module('myapp.services.serviceA')); // load the service being tested
beforeEach(inject(function (_serviceA_, _settings_) {
serviceA = _serviceA_;
settings = _settings_;
}));
container
for this test suite, all calls to the Settings service will be handled by the mock, which has the same interface as the real one, but returns dummy values.
Notice that you can load this service anywhere.
(If, by any reason, you needed to use the real implementation, you can load the real implementation before the mock and use spyOn for that particular case to delegate the call to the real implementation.)
Normally you'll place the mocks module outside of the app folder. I have a test folder with the unit tests, e2e tests and a lib folder with the angular-mocks.js file. I place my mocks there too.
Tell karma the files you need for the tests:
files: [
'app/lib/jquery/jquery-1.9.1.js',
'test/lib/jasmine-jquery.js',
'app/lib/angular/angular.js',
'app/lib/angular/angular-*.js',
'test/lib/angular/angular-mocks.js',
'test/lib/myapp/*.js', /* this is mine */
'app/js/**/*.js',
'test/unit/**/*.js'
],
The file tests/lib/myapp.mocks.settings.js looks just like any other module:
(function () {
"use strict";
var m = angular.module('myapp.mocks.settings', []);
m.service('settings', function () { ... })
})
Second problem (optional): you want to change quickly the dummy values. In the example, the settings service fetches an object from the server when it is instantiated for the first time. then, the service has getters for all fields. This is kind of a proxy to the server: instead of sending a request everytime you need a value, fetch a bunch of them and save them locally. In my application, settings don't change in the server in run-time.
Something like:
1. fetch http://example.org/api/settings
2. var localSettings = fetchedSettings;
3 getFieldA: function() { return localSettings.fieldA; }
Go and pollute the global namespace. I created a file settings.data.js with a content like:
var SETTINGS_RESPONSE = { fieldA: 42 };
the mock service uses this global variable in the factory to instantiate localSettings

Resources