301 Software Engineering
301 Software Engineering
Generally, the software goes under four level of testing: Unit Testing, Integration Testing, System
Testing, and Acceptance Testing but sometimes due to time consumption software testers does
minimal unit testing but skipping of unit testing may lead to higher defects during Integration Testing,
System Testing, and Acceptance Testing or even during Beta Testing which takes place after the
completion of software application.
Integration testing
Integration testing is the second level of the software testing process comes after unit testing. In this
testing, units or individual components of the software are tested in a group. The focus of the
integration testing level is to expose defects at the time of interaction between integrated components
or units.
Unit testing uses modules for testing purpose, and these modules are combined and tested in
integration testing. The Software is developed with a number of software modules that are coded by
different coders or programmers. The goal of integration testing is to check the correctness of
communication among all the modules.
Once all the components or
modules are working
independently, then we need to
check the data flow between the
dependent modules is known
as integration testing.
Let us see one sample example
Activities:
Unit Testing
Integration Testing
System Testing
User Acceptance Testing
Software testing tactics:
If we want to ensure that our software is bug-free or stable, we must perform the various types of
software testing because testing is the only method that makes our application bug-free.
Functional Testing
The test engineer will check all the components
systematically against requirement specifications is
known as functional testing. Functional testing is
also known as Component testing.
In functional testing, all the components are tested
by giving the value, defining the output, and
validating the actual output with the expected value.
Functional testing is a part of black-box testing as its emphases on application requirement rather than
actual code. The test engineer has to test only the program instead of the system.
1. Unit Testing
Unit testing is the first level of functional testing in order to test any software. In this, the test engineer
will test the module of an application independently or test all the module functionality is called unit
testing.
The primary objective of executing the unit testing is to confirm the unit components with their
performance. Here, a unit is defined as a single testable function of a software or an application. And it
is verified throughout the specified application development phase.
2. Integration Testing
Once we are successfully implementing the unit testing, we will go integration testing
. It is the second level of functional testing, where we test the data flow between dependent modules or
interface between two features is called integration testing.
The purpose of executing the integration testing is to test the statement's accuracy between each
module.
Types of Integration Testing
Integration testing is also further divided into the
following parts:
o Incremental Testing
o Non-Incremental Testing
Incremental Integration Testing
Whenever there is a clear relationship between
modules, we go for incremental integration testing. Suppose, we take two modules and analysis the
data flow between them if they are working fine or not.
If these modules are working fine, then we can add one more module and test again. And we can
continue with the same process to get better results.
In other words, we can say that incrementally adding up the modules and test the data flow between
the modules is known as Incremental integration
testing.
Types of Incremental Integration Testing
Incremental integration testing can further classify
into two parts, which are as follows:
1. Top-down Incremental Integration
Testing
2. Bottom-up Incremental Integration
Testing
1. Performance Testing
In performance testing, the test engineer will test the working of an application by applying some load.
In this type of non-functional testing, the test engineer will only focus on several aspects, such
as Response time, Load, scalability,
and Stability of the software or an
application.
Classification of Performance
Testing
Performance testing includes the
various types of testing, which are as
follows:
o Load Testing
o Stress Testing
As we can see in the above image that all of these testing levels have a specific objective which
specifies the value to the software development lifecycle.
For our better understanding, let's see them one by one:
Level1: Unit Testing
Unit testing is the first level of software testing, which is used to test if software modules are
satisfying the given requirement or not.
The first level of testing involves analyzing each unit or an individual component of the software
application.
Unit testing is also the first level of functional testing
The primary purpose of executing unit testing is to validate unit components with their performance.
A unit component is an individual function or regulation of the application, or we can say that it is the
smallest testable part of the software. The reason of performing the unit testing is to test the
correctness of inaccessible code.
Unit testing will help the test engineer and developers in order to understand the base of code that
makes them able to change defect causing code quickly. The developers implement the unit.
Level2: Integration Testing
The second level of software testing is the integration testing. The integration testing process comes
after unit testing.
It is mainly used to test the data flow from one module or component to other modules.
In integration testing, the test engineer tests the units or separate components or modules of the
software in a group.
The primary purpose of executing the integration testing is to identify the defects at the interaction
between integrated components or units.
When each component or module works separately, we need to check the data flow between the
dependent modules, and this process is known as integration testing.
We only go for the integration testing when the functional testing has been completed successfully on
each application module.
In simple words, we can say that integration testing aims to evaluate the accuracy of communication
among all the modules.
If – Then – Else –
While – Do
Switch – Case
Cyclomatic Complexity
The cyclomatic complexity V(G) is said to be a measure of the logical complexity of a program. It can
be calculated using three different formulae:
1. Formula based on edges and nodes :
V (G) = e - n + 2*P
Where,
e is number of edges
n is number of vertices
P is number of connected components.
For example, consider first graph given above,
where, e = 4, n = 4 and p = 1
So,
Cyclomatic complexity V(G)
=4-4+2*1
=2
2. Formula based on Decision Nodes :
V (G) = d + P
where,
d is number of decision nodes
P is number of connected nodes.
For example, consider first graph given above,
where, d = 1 and p = 1
So,
Cyclomatic Complexity V(G)
=1+1
=2
1. Formula based on Regions :
V(G) = number of regions in the graph
For example, consider first graph given above,
Cyclomatic complexity V(G)
= 1 (for Region 1) + 1 (for Region 2)
=2
Hence, using all the three above formulae, the cyclomatic complexity obtained remains same. All
these three formulae can be used to compute and verify the cyclomatic complexity of the flow graph.
Note –
1. For one function [e.g. Main ( ) or Factorial ( ) ], only one flow graph is constructed. If in a
program, there are multiple functions, then a separate flow graph is constructed for each one of
When a software is modified, it is still necessary to test the changes made in the software which as a
result, requires path testing.
Unit Testing
When a developer writes the code, he or she tests the structure of the program or module themselves
first. This is why basis path testing requires enough knowledge about the structure of the code.
Integration Testing
When one module calls other modules, there are high chances of Interface errors. In order to avoid
the case of such errors, path testing is performed to test all the paths on the interfaces of the modules.
Testing Effort
Since the basis path testing technique takes into account the complexity of the software (i.e.,
program or module) while computing the cyclomatic complexity, therefore it is intuitive to note that
RCR Institute of Management and Technology Page 31
Prepared By Mrs. P.Lalitha Software Engineering
testing effort in case of basis path testing is directly proportional to the complexity of the software or
program.
Object –Oriented Testing Methods
Test case design methods for OO software are still evolving. However, an
overall approach to OO test case design has been defined by Berard :
1. Each test case should be uniquely identified and explicitly associated with the class to be
tested.
2. The purpose of the test should be stated.
3. A list of testing steps should be developed for each test and should contain:
a. A list of specified states for the object that is to be tested.
b. A list of messages and operations that will be exercised as a consequence of the test.
c. A list of exceptions that may occur as the object is tested.
d. A list of external conditions (i.e., changes in the environment external to the software that
must exist in order to properly conduct the test).
e. Supplementary information that will aid in understanding or implementing the test.
The OO class is the target for test case design. Because attributes and operations are
encapsulated, testing operations outside of the class is generally unproductive. Although
encapsulation is an essential design concept for OO, it can create a minor obstacle when
testing. As Binder notes, “Testing requires reporting on the concrete and abstract state of an
object.” Yet, encapsulation can make this information somewhat difficult to obtain. Unless
built-in operations are provided to report the values for class attributes, a snapshot of the state
of an object may be difficult to acquire.
Inheritance also leads to additional challenges for the test case designer. We have
already noted that each new context of usage requires retesting, even though reuse has been
achieved. In addition, multiple inheritance complicates testing further by increasing the
number of contexts for which testing is required. If subclasses instantiated from a super class
are used within the same problem domain, it is likely that the set of test cases derived for the
super class can be used when testing the subclass. However, if the subclass is used in an
entirely different context, the super class test cases will have little applicability and a new set
of tests must be designed.
Applicability of Conventional Test Case Design Methods
The white-box testing methods can be applied to the operations defined for a class.
Basis path, loop testing, or data flow techniques can help to ensure that every statement in an
operation has been tested. However, the concise structure of many class operations causes
some to argue that the effort applied to white-box testing might be better redirected to tests at
a class level.
Black-box testing methods are as appropriate for OO systems as they are for systems
developed using conventional software engineering methods. Use-cases can provide useful
input in the design of black-box and state-based tests.
Fault-Based Testing
The object of fault-based testing within an OO system is to design tests that have a high
likelihood of uncovering plausible faults. Because the product or system must conform to
Deep structure refers to the internal technical details of an OO program. That is, the
structure that is understood by examining the design and/or code. Deep structure testing is
designed to exercise dependencies, behaviors, and communication mechanisms that have been
established as part of the system and object design of OO software.
The tests to be designed should achieve all state coverage. That is, the operation sequences
should cause the account class to make transition through all allowable states:
test case s1: open•setupAccnt•deposit (initial)•withdraw (final)•close
It should be noted that this sequence is identical to the minimum test sequence . Adding
additional test sequences to the minimum sequence,
test case s2: open•setupAccnt•deposit(initial)•deposit•balance•credit•withdraw
(final)•close
test case s3: open•setupAccnt•deposit(initial)•deposit•withdraw•accntInfo•withdraw
(final)•close
Still more test cases could be derived to ensure that all behaviors for the class have been
adequately exercised. In situations in which the class behavior results in a collaboration with
one or more classes, multiple STDs are used to track the behavioral flow of the system.
The state model can be traversed in a “breadth-first” manner. In this context, breadth first
implies that a test case exercise a single transition and that when a new transition is to be
tested only previously tested transitions are used.
Consider the credit card object discussed earlier. The initial state of credit card is undefined
(i.e., no credit card number has been provided). Upon reading the credit card during a sale, the
object takes on a defined state; that is, the attributes card number and expiration date, along
with bank specific identifiers are defined. The credit card is submitted when it is sent for
authorization and it is approved when authorization is received. The transition of credit card
from one state to another can be tested by deriving test cases that cause the transition to occur.