AngularJS Testing – Karma Protractor Cypress Guide
Using Selenium for testing AngularJS applications isn’t ideal due to the asynchronous nature of these apps. Selenium struggles to manage asynchronous calls effectively, leading to unreliable test outcomes. To address this challenge, it’s essential to leverage AngularJS-specific testing tools, which are designed to handle asynchronous behavior seamlessly. Below, we explore some of the best practices for testing AngularJS applications.
Unit Testing in AngularJS
AngularJS makes unit testing simpler by offering dependency injection for XHR requests. This feature allows testers to simulate backend requests efficiently during testing. Additionally, the model can be verified by directly modifying the DOM, ensuring that each function works correctly in isolation. This modular approach enables individual functions to be tested independently, resulting in more reliable outcomes and easier bug detection.
Why Use Cypress, Karma, and Protractor for AngularJS Testing?
These tools provide robust solutions for testing AngularJS applications:
- Cypress: Best suited for end-to-end testing with real-time feedback and support for asynchronous code.
- Karma: Excellent for running unit tests across multiple browsers, ensuring code stability.
- Protractor: Built explicitly for Angular apps, offering seamless handling of Angular-specific elements and events.
By using the right tools and techniques, testers can overcome the limitations posed by Selenium and ensure high-quality testing outcomes for AngularJS applications.
What is Karma?
Karma is a powerful JavaScript test runner developed by the AngularJS team, designed to facilitate efficient testing of AngularJS applications. When it comes to testing, Karma stands out as one of the top tools for AngularJS development.
Karma works seamlessly with Jasmine, a popular testing framework for JavaScript. While Jasmine handles the structure of the tests, Karma provides the necessary environment to run those tests, making the testing process more manageable.
How to Install Karma
To use Karma, Node.js must be installed on your system. Once Node.js is ready, Karma can be installed using the Node Package Manager (npm). Here’s how you can install Karma locally and globally:
Step 1: Install Karma locally using the following command:
npm install karma –save-dev
This command installs Karma along with its dependencies, which will be listed in the package.json
file.
Step 2: Install Karma globally (optional but recommended for ease of use):
npm install -g karma
The -g
flag makes Karma accessible from any directory in your system, streamlining your workflow.
Testing AngularJS Applications with Karma
Once Karma is installed, you’ll need to add plugins that enable you to use specific frameworks and browsers for testing. To integrate Jasmine and Google Chrome, run the following command:
npm install karma-jasmine karma-chrome-launcher –save-dev
Or Run the below command:
mkdir tests // for making tests directory
touch tests/test1.controller.test.JS //For creating a test called test1
After creating a test, now it is time to put code in test1.
describe(test1,function(){
beforeEach(module(test1));
var$controller;
beforeEach(inject(function(_$controller_){
$controller=_$controller_;
}));
describe(‘sub’,function(){
it(‘1 – 1 should equal 0’,function(){
var$scope={};
varcontroller=$controller(test1Controller,{$scope:$scope});
$scope.x=1;
$scope.y= 1;
$scope.sub();
expect($scope.z).toBe(0);
});
});
});
Now, after creating the test you should know how to create a test runner, and before creating that we should know the configuration required for the test runner. For configuring the test runner perform the following steps.
karma init karma.conf.JS
Now, for running the tests using the test runner run the following command.
karma start karma.conf.JS
The test output should look like the underlying code.
> @ test /Users/devuser/repos/test1
> ./node_modules/karma/bin/karma start karma.conf.JS
INFO [karma]: Karma server started at http://localhost:8080/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 80]: Connected on socket 2absOkNfa1asasaX0fCJ with id 66276373
Chrome 80 test1 encountered a declaration exception FAILED
ReferenceError: module is not defined
at Suite.<anonymous>(/Users/devuser/repos/repo1/tests/test1.controller.test.JS:3:13)
at /Users/devuser/repos/repo1/tests/test1.controller.test.JS:1:1
Chrome 80): Executed 1 of 1 (1 FAILED) ERROR (0.01 secs / 0.005 secs)
Now, add the following lines to your package.JSon.
{
“scripts”:{
“test”:”karma start karma.conf.JS”
},
Now with the help of this script, we will be able to run any test using npm command. Using the below command, run the jasmine tests.
npmtest
Now, it is time to add the controller logic and for adding it run the following commands.
mkdir app
touch app/test1.controller.JS
Add the following code in test1.controller.JS
angular.module(test1,[]).controller(‘testController’,functiontestController($scope){
$scope.sub=function(){
$scope.z=$scope.x-$scope.y;
};
});f
For adding the angular dependencies, run the following commands. Make a directory called lib in your project and then add all libraries in that folder.
mkdir lib
curl -o lib/angular.min.JShttps://code.angularJS.org/1.4.0-rc.2/angular.min.JS
curl -o lib/angular-mocks.JShttps://code.angularJS.org/1.4.0-rc.2/angular-mocks.JS
Now, it is time to edit the karma config file so that it comes to know about the test folder and the library folder so that jasmine tests can run successfully.
files:[
‘lib/angular.min.JS’,
‘lib/angular-mocks.JS’,
‘app/*.JS’,
‘tests/*.JS’
],
Now, run the tests using the npm test. Your test will run now successfully.
How to test AngularJS applications using Protractor?
Now, let’s take a test case in which we have to go to URL: https://angularJS.org, and then you have to type your name in the textbox. After entering you will see your name as Hello Name!
Now, let us start with the steps which are required for making this test case and to execute it. In your folder, you will have 2 files. One is spec.JS and the other is conf.JS. The logic for spec.JS which will be there in it.
describe(‘Enter yourname, function() {it(‘should add a Name as your name, function() {browser.get(‘https://angularJS.org’); element(by.model(‘yourName’)).sendKeys(‘Name’); var name= element(by.xpath(‘html/body/div[2]/div[1]/div[2]/div[2]/div/h1’));expect(name.getText()).toEqual(‘Hello Name!’); });});
Now, if you see that describe comes from the Jasmine framework. It is basically a module and it can be a class or a function. We are giving this module name as “Enter Your Name”. So, for starting the function we start it with describe keyword. Just like a class can have many methods or a TestNG class can have so many test cases. Similarly, in the Jasmine framework, it starts a new test case.
browser.get(‘https://angularJS.org’);
This command is used for opening the browser with URL mentioned as https://angularJS.org. Now, you must identify the elements. So, you have to inspect the element just like you do in Selenium. You can use By.model for the elements who have ng-model as an attribute.
You can store Web elements in a variable. You can declare a variable using var keyword. Now, it is time to have some assertions. You get the text out of this web element and then compare it to the expected text.
Now, you are done with spec.JS and let us start with the conf.JS. You have to define the path of spec here so that tests can be identified easily.
Paste the following code in conf.JS
exports.config = {seleniumAddress: ‘http://localhost:4444/wd/hub’, specs: [‘spec.JS’]};
Selenium address is the location where it can communicate with the selenium webdriver. Spcs tell the location of spec.JS
Now, for running the test, first navigate to the directory in which spec.JS and conf.JS are located. First thing to keep in mind that webdriver-manager should be started. If not started, you have to first start it with following command.
webdriver-manager start
Now, it’s time to run the configuration file. After starting the webdriver-manager plugin, run the config.JS file using protractor. Fire the following command.
protractor conf.JS
You have seen how many specs got passed and how many got failed.
Now let’s see how the failure is going to be reflected in the console. We make the assertion false.
Modify the code in spec.JS
describe(‘Enter your name, function() {it(‘should add a Name as your name, function() {browser.get(‘https://angularJS.org’); element(by.model(‘yourName’)).sendKeys(‘Name’); var name= element(by.xpath(‘html/body/div[2]/div[1]/div[2]/div[2]/div/h1’));expect(name.getText()).toEqual(‘Hello!’); });});
You will see F which means failed test case. You will get to know the complete description where the test case got failed.
Now, you must be imagining how would the reports be integrated with Jasmine. Let’s install the Jasmine reporter. Run the following command:
npm install –save-dev jasmine-reporters@^2.0.0
If you want jasmine reporter to installed globally. For installing globally, run the following command.
npm install –g jasmine-reporters@^2.0.0
You have to now modify the conf.JS. You have to add Jasmine reporter in it. Add the following code in it.
exports.config = {seleniumAddress: ‘http://localhost:4444/wd/hub’, capabilities: { ‘browserName’: ‘Chrome’ }, specs: [‘spec.JS’], framework: ‘jasmine2’ ,onPrepare: function() { var jasmineReporters = require(‘C:/Users/User1/node_modules/jasmine-reporters’);jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter(null, true, true) ); } };
Now, run the tests using protractor conf.JS. You will see the junitresult.xml in the folder path given in conf.JS.
Open the XML file and see the result of the test case. In this way, you can take the help of protractor to test angular JS websites.
Testing AngularJS Applications Using Cypress
Cypress is an advanced end-to-end (E2E) testing framework that works closely with your application, offering a thin layer between the production and testing code. Designed specifically for JavaScript applications, Cypress makes testing AngularJS apps seamless and efficient.
In this guide, we’ll explore how Cypress simplifies the testing process, the tools it bundles, and the essential commands you need to get started. If you’re looking to enhance your AngularJS testing workflow, Cypress provides the perfect framework with its robust capabilities and easy setup.
npmicypress -D
Now for opening the cypress test runner, run the following command.
npx cypress open
If you want your application and Cypress to run at the same time then you have to make some changes in your package.JSon.
“cypress”: “concurrently \”ng serve\” \”cypress open\””
Add these lines in package.JSon.
Now, run the following command
npm run cypress
When you add a new project in cypress then you will have below folder structure.
Fixtures have static data that has to be used by your tests. You can use them by cy.fixture() command. In the integration folder, you will have your integration tests. The plugin helps you to tweak to your test cases. Just like plugins have a file named index.JS which have a method which will run before every spec file. In Support files, you can have your reusable code.
Now, it is time to create your first test in the integration folder. You name it as test1.spec.JS. You will see it in the Cypress test runner also. Cypress API is present under the global cy project. Now let us put some code in it.
describe(“Test1”, () => {
it(“should visit home page”, () => {
cy.visit(“http://localhost:4200/login”);
});
});
It makes use of description and it blocks from the mocha syntax. It makes the beginning of the test cases. Once you will run this test In the test explorer, on the right side, the execution starts.
When you will run Cypress for the first time, you will see that the cypress.JSon file will get generated. In this, you can store your configuration values. Now let’s store our base URL in cypress. JSON so that we don’t have to change the URL in every test case.
{
“baseUrl”:”http://localhost:4200″
}
It’s time to change the code in spec.JS also.
describe(“Test1”,()=>{
it(“shouldvisit home page”,()=>{
cy.visit(“/login”);
});
});
Now for getting webelement, you can make use of a cypress selector background in the test runner. It is present on the left side of the test runner. You can get the XPath from there.
Use this way to get the webelements.
cy.get(‘.btn-link’).click();
cy.url().should(‘include’, ‘/register’)
This assertion will check the check has registered keywords in it. Hence, we are done with the first test case in cypress.
Conclusion Or Final Thoughts on AngularJS Testing
In this blog, we explored various strategies for effectively testing AngularJS applications. By applying these methods, you can ensure thorough testing and deliver high-quality software. Focus on optimizing your code and implementing best practices for seamless test integration. This will not only enhance your testing process but also build confidence with your clients through clear and reliable test metrics.
Leave a Reply