0% found this document useful (0 votes)
24 views36 pages

ExpressJS Web App Testing Guide

The document covers various aspects of web design, focusing on Express.js and web app testing. It explains the Node.js process model, core modules, and the advantages of using Express.js for web application development. Additionally, it emphasizes the importance of web UI testing, methods for conducting it, and best practices for ensuring functionality and visual consistency.

Uploaded by

yarychroma
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
24 views36 pages

ExpressJS Web App Testing Guide

The document covers various aspects of web design, focusing on Express.js and web app testing. It explains the Node.js process model, core modules, and the advantages of using Express.js for web application development. Additionally, it emphasizes the importance of web UI testing, methods for conducting it, and best practices for ensuring functionality and visual consistency.

Uploaded by

yarychroma
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd

Web design

Lecture #13. ExpressJS. Web app testing


The organization issues

Use this link to confirm your attendance in the lecture

Лабораторна робота №1

Лабораторна робота №2

Лабораторна робота №3

2
[Link] Process Model
Traditional Web Server Model
In the traditional web server model, each request is handled by a dedicated
thread from the thread pool. If no thread is available in the thread pool at
any point of time then the request waits till the next available thread.
Dedicated thread executes a particular request and does not return to thread pool
until it completes the execution and returns a response.
[Link] Process Model
[Link] runs in a single process and the application code runs in a single
thread and thereby needs less resources than other platforms. All the user
requests to your web application will be handled by a single thread and all the
I/O work or long running job is performed asynchronously for a particular
request. So, this single thread doesn't have to wait for the request to
complete and is free to handle the next request. When asynchronous I/O work
completes then it processes the request further and sends the response.

3
Event Loop Example
const foo = () => [Link]("First");
Source
const bar = () => setTimeout(() => [Link]("Second"), 500);
const baz = () => [Link]("Third");

bar();
foo();
baz();

4
[Link] Core Modules

http http module includes classes, methods and events to create [Link]
http server.
url url module includes methods for URL resolution and parsing.
querystring querystring module includes methods to deal with query
string.
path path module includes methods to deal with file paths.
fs fs module includes classes, methods, and events to work with file I/O.
util util module includes utility functions useful for programmers.

5
Load and Use Core http Module
var http = require('http');
var server = [Link](function(req, res){
//write code here
});
[Link](5000);
In the above example, require() function returns an object because http module
returns its functionality as an object, you can then use its properties and methods
using dot notation e.g. [Link]().

6
Writing Simple Module
In [Link], module should be placed in a separate JavaScript file. So, create a
[Link] file and write the following code in it.
var log = {
info: function (info) {
[Link]('Info: ' + info);
},
warning:function (warning) {
[Link]('Warning: ' + warning);
},
error:function (error) {
[Link]('Error: ' + error); var myLogModule = require('./[Link]');
} [Link]('[Link] started');
};
C:\> node [Link]
[Link] = log Info: [Link] started
7
NPM - Node Package Manager
Node Package Manager (NPM) is a command line tool that installs, updates or
uninstalls [Link] packages in your application. It is also an online repository for
open-source [Link] packages. The node community around the world creates
useful modules and publishes them as packages in this repository.
Install Package Locally
C:\>npm install <package name> Uninstall Packages
Add Dependency into [Link] C:\MyNodeProj> npm uninstall
C:\MyNodeProj> npm install express --save express
Install Package Globally
C:\MyNodeProj> npm install -g express

8
[Link]
A [Link] file, usually present in the project root, contains metadata about
your app or module as well as the list of dependencies to install from npm when
running npm install.
To initialize a [Link] type npm init in your command prompt.

To create a [Link] with default values use:

npm init --yes


# or
npm init -y

9
properties of [Link]
"scripts": {
"test": "vows --spec --isolate",
"start": "node [Link]",
{ "predeploy": "echo About to deploy",
"name": "module-name", "postdeploy": "echo Deployed",
"version": "10.3.1", "prepublish": "coffee --bare --compile --output
"description": "An example module", lib/foo src/foo/*.coffee"
"author": "Your Name },
<[Link]@[Link]>", "main": "lib/[Link]",
"contributors": [{ "dependencies": {
"name": "Foo Bar", "express": "4.2.x"
"email": "[Link]@[Link]" },
}], "devDependencies": {
"bin": { "assume": "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2
"module-name": "./bin/module-name" <3.0.0"
}, },
"files": [
"lib/[Link]"
] 10
Create [Link] Web Server
[Link] makes it easy to create a simple web server that processes incoming
requests asynchronously.

The following example is a simple [Link] web server contained in [Link] file.

[Link]
var http = require('http'); // 1 - Import [Link] core module
var server = [Link](function (req, res) { // 2 -
creating server
//handle incomming requests here..
});
[Link](5000); //3 - listen for any incoming requests

[Link]('[Link] web server at port 5000 is running..')


C:\> node [Link]
[Link] web server at port 5000 is running..
11
Handle HTTP Request
[Link] Copy
var http = require('http'); // Import [Link] core module

var server = [Link](function (req, res) { //create web server


if ([Link] == '/') { //check the URL of the current request
// set response header
[Link](200, { 'Content-Type': 'text/html' });
// set response content
[Link]('<html><body><p>This is home Page.</p></body></html>');
[Link]();
}
else
[Link]('Invalid Request!');
});

[Link](5000); //6 - listen for any incoming requests


[Link]('[Link] web server at port 5000 is running..')
12
[Link]
"Express is a fast, unopinionated minimalist web framework for [Link]" - official
web site: [Link]
[Link] is a web application framework for [Link]. It provides various features
that make web application development fast and easy which otherwise takes more
time using only [Link].
[Link] is based on the [Link] middleware module called connect which in turn
uses http module. So, any middleware which is based on connect will also work
with [Link].

13
Advantages of [Link]
● Makes [Link] web application development fast and easy.
● Easy to configure and customize.
● Allows you to define routes of your application based on HTTP methods and
URLs.
● Includes various middleware modules which you can use to perform
additional tasks on request and response.
● Easy to integrate with different template engines like Jade, Vash, EJS etc.
● Allows you to define an error handling middleware.
● Easy to serve static files and resources of your application.
● Allows you to create REST API server.
● Easy to connect with databases such as MongoDB, Redis, MySQL

14
[Link] Web Application

[Link]: [Link] Web Server


var express = require('express');
var app = express();
// define routes here..
var server = [Link](5000, function () {
[Link]('Node server is running..');
});

15
Configure Routes in [Link]
var express = require('express');
var app = express();

[Link]('/', function (req, res) {


[Link]('<html><body><h1>Hello World</h1></body></html>');
});

[Link]('/submit-data', function (req, res) {


[Link]('POST Request');
});

[Link]('/update-data', function (req, res) {


[Link]('PUT Request');
});

16
Serve Static Resources using
[Link]
[Link] Copy
var express = require('express');
var app = express();
//setting middleware
[Link]([Link](__dirname + 'public')); //Serves resources from public
folder
var server = [Link](5000);

17
Data Access in [Link]

Relational
Databases Driver NPM Command

MS SQL Server mssql npm install mssql

Oracle oracledb npm install oracledb

MySQL MySQL npm install mysql

PostgreSQL pg npm install pg

SQLite sqlite3 npm install sqlite3

18
SQLite [Link]
const sqlite3 = require('sqlite3').verbose();

// open database in memory


let db = new [Link](':memory:', (err) => { // MEMORY
// let db = new [Link]('./db/[Link]', (err) => { // FILE
if (err) {
return [Link]([Link]);
}
[Link]('Connected to the in-memory SQlite database.');
});
// close the database connection
[Link]((err) => {
if (err) {
return [Link]([Link]);
}
[Link]('Close the database connection.');
19
});
SQLite SELECT
const sqlite3 = require('sqlite3').verbose();
// open the database
let db = new [Link]('../db/[Link]');
let sql = `SELECT FirstName firstName, LastName lastName, Email email
FROM customers
WHERE Country = ?
ORDER BY FirstName`;
[Link](sql, ['Ukraine'], (err, row) => {
if (err) {
throw err;
}
[Link](`${[Link]} ${[Link]} - ${[Link]}`);
});

// close the database connection


[Link]();
20
Example: Ajax, NodeJS, Express
[Link]
var express = require('express');
var path = require('path');
var app = express();
[Link]([Link]('public'));
[Link]('/home', (req, res) => {
[Link]([Link](__dirname, './[Link]'));
})
[Link]('/', function (req, res) {
[Link]('<html><body><h1>Hello World</h1></body></html>');
});
[Link]('/get-data', function (req, res) {
[Link]({'message': 'Greetings from NodeJS!'});
});

[Link](5000); 21
Example: Ajax, NodeJS, Express
[Link]
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<p id='data'>Data is loading... </p>
<script src="[Link]
<script>
async function getData() {
let p = [Link]('#data');
var result = await axios('/get-data/');
var timeout = await new Promise(() => setTimeout(() => {
[Link] = [Link]['message']}, 3000));
}
getData();
</script>
</body>
22
</html>
Example: Ajax, NodeJS, Express
(refreshing every second)
<html lang="en">
<head>
<title>Example</title>
</head>
<body>
<p id='data'>Data is loading... </p>
<script src="[Link]
<script>
function getData() {
let p = [Link]('#data');
setInterval(async ()=>{
var result = await axios('/get-data/');
[Link] = [Link]['message'];
}, 1000);
}
getData();
</script> 23
Registration & Authentication

Authentication using [Link], [Link], and SQLite


The Repository

24
Web UI Testing importance
Web UI testing is crucial for ensuring that web applications function
correctly, meet user requirements, and provide a positive user
experience. Here's why it's important and some ways to conduct it
effectively:
User Experience (UX) Assurance: The UI is what users interact with
directly. Testing ensures that the interface is intuitive, responsive, and
aesthetically pleasing.
Functional Validation: UI testing verifies that all elements on the page
function as expected. This includes buttons, links, forms, menus, etc.
Cross-browser and Cross-device Compatibility: Ensuring that your UI
works consistently across different browsers and devices is essential for
reaching a broad audience.
Accessibility Compliance: Testing ensures that the UI is accessible to
users with disabilities, meeting relevant standards such as WCAG (Web
Content Accessibility Guidelines).
Brand Image and Credibility: A well-designed and error-free UI reflects
positively on the brand and instills confidence in users. 25
Ways to Conduct Web UI Testing
Manual Testing:
Exploratory Testing: Manual exploration of the application to uncover UI issues,
usability problems, and inconsistencies.
Usability Testing: Involves real users to evaluate the UI's ease of use, efficiency,
and overall user satisfaction.

Automated Testing:
Functional Testing: Automated tests to verify that UI elements function correctly.
Tools like Selenium, Cypress, or Puppeteer can be used.
Visual Testing: Tools like Applitools or Percy capture screenshots of UI
components and compare them to baseline images to detect visual regressions.
Cross-browser Testing: Tools like BrowserStack or Sauce Labs automate testing
across various browsers and devices.
Accessibility Testing: Tools like Axe or Pa11y can be used to automatically test
for accessibility issues.

26
Ways to Conduct Web UI Testing
(2)
Responsive Design Testing:
Ensures that the UI adapts and displays correctly across different screen sizes.
Tools like Browser's developer tools or Responsinator can assist in this.

Performance Testing:
Evaluates how quickly the UI responds and loads under different conditions. Tools
like Lighthouse or GTmetrix can be used for performance analysis.

Localization and Internationalization Testing:


Ensures that the UI works seamlessly in different languages and locales.

Regression Testing:
Regularly test the UI to ensure that new features or changes haven't introduced
any unintended side effects.

Security Testing:
While not purely UI testing, it's important to ensure that the UI doesn't expose
security vulnerabilities such as XSS (Cross-Site Scripting) or CSRF (Cross-Site 27
Best practices
Early Testing: Start testing early in the development process to catch issues
sooner.
Test Coverage: Ensure that UI testing covers all critical paths and user
interactions.
Test Data: Use realistic data sets for testing to mimic real-world scenarios.
Regular Updates: Keep tests updated as the UI evolves.
Collaboration: Encourage collaboration between developers, designers, and
testers to ensure a comprehensive approach to UI testing.
Documentation: Document UI testing procedures, results, and issues for future
reference and improvement.

28
UI Testing

Functionality Verification: UI testing ensures that all user-facing functionalities


of the application work as intended. This includes testing user interactions,
navigation, input validation, and responsiveness to user actions.
Visual Consistency and Compatibility: UI testing checks the visual aspects of
the application's interface to ensure consistency across different devices and
browsers. It verifies the layout, fonts, colors, images, and alignment to provide a
seamless user experience.
Automation and Manual Testing: UI testing involves a combination of
automated and manual testing. Automation is used for repetitive tasks and
regression testing, while manual testing is essential for exploratory testing and
detecting issues such as usability problems or visual inconsistencies that may not
be easily captured by automated tests.
Manual vs. automated testing

Manual testing is done in person, by clicking through the application or


interacting with the software and APIs with the appropriate tooling.
This is very expensive as it requires someone to set up an environment and
execute the tests themselves, and it can be prone to human error as the tester
might make typos or omit steps in the test script.
Automated tests, on the other hand, are performed by a machine that executes
a test script that has been written in advance.
It's much more robust and reliable than automated tests – but the quality of
your automated tests depends on how well your test scripts have been written.
The different types of tests
Unit tests
Unit tests are very low level, close to the source of your application. They
consist in testing individual methods and functions of the classes, components or
modules used by your software. Unit tests are in general quite cheap to
automate and can be run very quickly by a continuous integration server.
Purpose: testing individual (isolated) functions, classes, components on
programming language level.
Tools: Vitest, Codeception, PHPUnit, Jest, Mocha, etc.
Integration tests
Integration tests verify that different modules or services used by your application work well
together. For example, it can be testing the interaction with the database or making sure that
microservices work together as expected. These types of tests are more expensive to run as
they require multiple parts of the application to be up and running.
Purpose: testing processes or components to behave as expected, including the side effects.
Tools: Codeception, Jest, Mocha, etc.
In unit tests, we mock all dependencies and external functions to test isolated pieces of code.
In integration tests, conversely, we keep most of the dependencies in place and test how
well individual units play with each other.
Functional tests

Functional tests focus on the business requirements of an application. They


only verify the output of an action and do not check the intermediate
states of the system when performing that action.

There is sometimes a confusion between integration tests and functional


tests as they both require multiple components to interact with each other. The
difference is that an integration test may simply verify that you can query
the database while a functional test would expect to get a specific value
from the database as defined by the product requirements.
End-to-end tests
End-to-end testing replicates a user behavior with the software in a complete
application environment. It verifies that various user flows work as expected
and can be as simple as loading a web page or logging in or much more complex
scenarios verifying email notifications, online payments, etc.
End-to-end tests are very useful, but they're expensive to perform and can be
hard to maintain when they're automated. It is recommended to have a few key
end-to-end tests and rely more on lower level types of testing (unit and
integration tests) to be able to quickly identify breaking changes.
Purpose: testing the entire system on browser level; behaving like a real user.
Tools: Codeception, TestCafe, Cypress, Selenium etc.
While unit and integration tests focus on testing code, end-to-end tests
(sometimes called E2E, Acceptance or Functional tests) focus on testing site
features.
Acceptance testing

Acceptance tests are formal tests executed to verify if a system satisfies its
business requirements. They require the entire application to be up and
running and focus on replicating user behaviors. But they can also go further
and measure the performance of the system and reject changes if certain goals
are not met.
Differences between Acceptance
and E2E Testing
1. Purpose / Goal
Acceptance Tests check if the system satisfies business or customer requirements.
E2E Tests check if all parts of the system work together technically.

2. Perspective
Acceptance Testing is from the business or user perspective (e.g., "Can a user buy a product?").
E2E Testing is from the technical user flow perspective (e.g., "Does the 'Buy' button work end-
to-end?")

3. Ownership
Acceptance Tests are often defined by Product Owners, Business Analysts, or QA, possibly
involving non-technical stakeholders.
E2E Tests are usually written by developers or QA engineers using automated tools.

4. Automation: Acceptance tests may be manual or automated. E2E tests are mostly
automated.
36
5. Timing: Acceptance often happens near release ("final check before delivery"). E2E tests run

Common questions

Powered by AI

Unit tests and integration tests are both critical components of a robust testing strategy. Unit tests focus on testing individual methods, functions, or classes in isolation, ensuring each component works correctly on its own . They are typically quick to run and easy to automate, making them suitable for continuous integration processes . In contrast, integration tests verify that different modules or services within an application work together as intended, necessitating multiple components to be operational simultaneously . Integration tests ensure that modules integrate seamlessly, test interactions with databases, and ensure that microservices communicate correctly . Together, these tests enhance software reliability by identifying defects at both the component and interaction levels .

Node.js modules enhance functionality and maintainability by promoting code reusability and separation of concerns . By encapsulating functionalities into discrete modules, developers can break large applications into smaller, manageable pieces. This modular architecture allows shared functionalities across different parts of the application, storage in separate files, and easy reuse via the require() function . Furthermore, creating custom modules like a logging module can standardize common processes across applications . Using npm, developers can access a vast repository of community-created modules, expediting the development process and simplifying dependency management .

Web UI testing ensures a positive user experience by verifying that the interface functions correctly, responds swiftly, and is visually appealing. Key methodologies include functional testing to validate user interactions and responsiveness, cross-browser testing for consistent performance across different environments, and accessibility testing to ensure compliance with accessibility standards like WCAG . Automated testing using tools like Selenium or Cypress can efficiently handle repetitive tasks and regression tests . Manual testing is employed for exploratory testing to uncover usability issues that automated tools might miss . Together, these methodologies ensure that all UI elements work seamlessly, contributing to a robust and user-friendly interface .

Express.js is a fast, unopinionated minimalist web framework that simplifies Node.js web application development . It offers easy configuration and customization, allowing developers to define routes based on HTTP methods and URLs seamlessly. Express.js supports various middleware modules that perform additional tasks on requests and responses, enhancing functionality compared to traditional Node.js . Developers benefit from integration with template engines such as Jade, Vash, and EJS, which simplifies rendering web pages dynamically. Moreover, it allows for easier error handling middleware integration and offers robust support for creating REST APIs and connecting with databases like MongoDB, Redis, and MySQL .

Handling HTTP requests using Node.js core modules involves manually creating servers and handling requests directly, which requires setting response headers and URLs manually, as well as managing the asynchrony of each request . This approach provides low-level control but can be cumbersome for larger applications. In contrast, Express.js abstracts these complexities, providing a more straightforward API to define routes and implement middleware, allowing developers to focus on high-level structures such as request handling logic and response management . Express.js also facilitates the integration of third-party middleware and template engines, streamlining the development process and enhancing application features beyond what's available with the core http module alone .

To improve performance and user experience, developers can implement several strategies. Firstly, optimizing asset delivery by minifying CSS and JavaScript files and compressing images can significantly reduce load times . Secondly, using Content Delivery Networks (CDNs) can help deliver content faster to users across different geographical locations . Utilizing modern JavaScript frameworks like Express.js allows for efficient handling of requests and quicker server response times . Employing caching strategies, such as HTTP caching or using in-memory caches like Redis, can reduce server load and improve response times . Additionally, ensuring cross-browser and cross-device compatibility through thorough UI testing is critical for maintaining a consistent user experience across platforms .

The Node.js process model operates with a single process and a single thread, handling all user requests asynchronously, unlike the traditional web server model where each request is handled by a dedicated thread from a thread pool . This asynchronous approach allows Node.js to manage I/O operations or long-running jobs without blocking the single thread, enabling it to handle other requests immediately and efficiently . The benefits include reduced resource consumption and the ability to handle a large number of concurrent connections without the need for additional threads, making Node.js highly scalable and suitable for real-time applications .

Asynchronous handling in Node.js significantly enhances the scalability of web applications by allowing a single-threaded architecture to manage multiple connections without the need to spawn new threads for each request . In synchronous models, each connection requires a dedicated thread, resulting in higher resource consumption and potential bottlenecks as thread limits are reached . Node.js, by processing I/O operations asynchronously, frees up its single thread to handle other incoming requests while awaiting operations to complete. This method enables the application to maintain high throughput with lower overhead, making it ideal for applications requiring real-time processing of data .

The package.json file functions as a manifest for a Node.js application, containing metadata about the application or module and listing all dependencies required for the project . It simplifies dependency management by allowing developers to install, update, or remove packages using npm commands, reflecting changes directly in package.json . When running npm install, the dependencies outlined in package.json are automatically installed, ensuring that all necessary modules are available and version-controlled for project consistency . Additionally, package.json includes scripts to automate tasks such as testing and deploying, contributing to efficient project management .

Designing a comprehensive UI testing strategy involves several key considerations. Early testing is crucial to detect and resolve issues early in the development lifecycle, reducing the cost and effort of fixing defects later . Ensuring test coverage for all critical user interactions and paths helps verify comprehensive functionality and user satisfaction . Using realistic test data simulates real-world scenarios, improving reliability and robustness . Regularly updating tests as the application evolves prevents tests from becoming obsolete, allowing for continuous quality assurance . Collaboration between developers, testers, and designers enhances the testing process by integrating diverse perspectives and expertise into test design. This strategy results in improved product quality, user satisfaction, and potentially reduced time to market through more reliable release cycles .

You might also like