Testing complex logical flow что это
Фундаментальная теория тестирования
В тестировании нет четких определений, как в физике, математике, которые при перефразировании становятся абсолютно неверными. Поэтому важно понимать процессы и подходы. В данной статье разберем основные определения теории тестирования.
Перейдем к основным понятиям
Тестирование программного обеспечения (Software Testing) — проверка соответствия реальных и ожидаемых результатов поведения программы, проводимая на конечном наборе тестов, выбранном определённым образом.
Цель тестирования — проверка соответствия ПО предъявляемым требованиям, обеспечение уверенности в качестве ПО, поиск очевидных ошибок в программном обеспечении, которые должны быть выявлены до того, как их обнаружат пользователи программы.
Для чего проводится тестирование ПО?
Принципы тестирования
QC (Quality Control) — Контроль качества продукта — анализ результатов тестирования и качества новых версий выпускаемого продукта.
К задачам контроля качества относятся:
К задачам обеспечения качества относятся:
Верификация и валидация — два понятия тесно связаны с процессами тестирования и обеспечения качества. К сожалению, их часто путают, хотя отличия между ними достаточно существенны.
Верификация (verification) — это процесс оценки системы, чтобы понять, удовлетворяют ли результаты текущего этапа разработки условиям, которые были сформулированы в его начале.
Валидация (validation) — это определение соответствия разрабатываемого ПО ожиданиям и потребностям пользователя, его требованиям к системе.
Пример: когда разрабатывали аэробус А310, то надо было сделать так, чтобы закрылки вставали в положение «торможение», когда шасси коснулись земли. Запрограммировали так, что когда шасси начинают крутиться, то закрылки ставим в положение «торможение». Но вот во время испытаний в Варшаве самолет выкатился за пределы полосы, так как была мокрая поверхность. Он проскользил, только потом был крутящий момент и они, закрылки, открылись. С точки зрения «верификации» — программа сработала, с точки зрения «валидации» — нет. Поэтому код изменили так, чтобы в момент изменения давления в шинах открывались закрылки.
Документацию, которая используется на проектах по разработке ПО, можно условно разделить на две группы:
Этапы тестирования:
Программный продукт проходит следующие стадии:
Требования
Требования — это спецификация (описание) того, что должно быть реализовано.
Требования описывают то, что необходимо реализовать, без детализации технической стороны решения.
Отчёт о дефекте (bug report) — документ, который содержит отчет о любом недостатке в компоненте или системе, который потенциально может привести компонент или систему к невозможности выполнить требуемую функцию.
Атрибуты отчета о дефекте:
Жизненный цикл бага
Severity vs Priority
Серьёзность (severity) показывает степень ущерба, который наносится проекту существованием дефекта. Severity выставляется тестировщиком.
Градация Серьезности дефекта (Severity):
Градация Приоритета дефекта (Priority):
Тестовые среды
Основные фазы тестирования
Основные виды тестирования ПО
Вид тестирования — это совокупность активностей, направленных на тестирование заданных характеристик системы или её части, основанная на конкретных целях.
Автор книги «A Practitioner’s Guide to Software Test Design», Lee Copeland, выделяет следующие техники тест-дизайна:
Методы тестирования
Тестирование белого ящика — метод тестирования ПО, который предполагает, что внутренняя структура/устройство/реализация системы известны тестировщику.
Согласно ISTQB, тестирование белого ящика — это:
Тестирование чёрного ящика — также известное как тестирование, основанное на спецификации или тестирование поведения — техника тестирования, основанная на работе исключительно с внешними интерфейсами тестируемой системы.
Согласно ISTQB, тестирование черного ящика — это:
Тестовая документация
Тест план (Test Plan) — это документ, который описывает весь объем работ по тестированию, начиная с описания объекта, стратегии, расписания, критериев начала и окончания тестирования, до необходимого в процессе работы оборудования, специальных знаний, а также оценки рисков.
Тест план должен отвечать на следующие вопросы:
Чаще всего чек-лист содержит только действия, без ожидаемого результата. Чек-лист менее формализован.
Тестовый сценарий (test case) — это артефакт, описывающий совокупность шагов, конкретных условий и параметров, необходимых для проверки реализации тестируемой функции или её части.
Атрибуты тест кейса:
Фундаментальная теория тестирования
Тестирование — это не точная наука. Тут нет чётких устоявшихся определений, которые можно собрать в словарь и выучить перед собеседованием. Каждый IT-проект уникален, что порождает огромное количество разной, часто противоречивой информации. Важным в тестировании, как и в любой профессии, становится понимание процессов и подходов. Важно не только знать, как называется тот или иной процесс, вид тестирования, а что он из себя представляет и для чего он нужен на проекте.
Перейдем к основным понятиям.
Тестирование программного обеспечения (Software Testing) — проверка соответствия реальных и ожидаемых результатов поведения программы, проводимая на конечном наборе тестов, выбранном определённым образом.
Цель тестирования — проверка соответствия ПО предъявляемым требованиям, обеспечение уверенности в качестве ПО, поиск очевидных ошибок в программном обеспечении, которые должны быть выявлены до того, как их обнаружат пользователи программы.
Принципы тестирования
Обеспечение качества (QA — Quality Assurance) и контроль качества (QC — Quality Control) — эти термины похожи на взаимозаменяемые, но разница между обеспечением качества и контролем качества все-таки есть, хоть на практике процессы и имеют некоторую схожесть.
QA (Quality Assurance) — Обеспечение качества продукта — изучение возможностей по изменению и улучшению процесса разработки, улучшению коммуникаций в команде, где тестирование является только одним из аспектов обеспечения качества.
Верификация и валидация — два понятия тесно связаны с процессами тестирования и обеспечения качества. К сожалению, их часто путают, хотя отличия между ними достаточно существенны.
Верификация (verification) — это процесс оценки системы, чтобы понять, удовлетворяют ли результаты текущего этапа разработки условиям, которые были сформулированы в его начале.
Валидация (validation) — это определение соответствия разрабатываемого ПО ожиданиям и потребностям пользователя, его требованиям к системе.
Пример: когда разрабатывали аэробус А310, то надо было сделать так, чтобы закрылки вставали в положение «торможение», когда шасси коснулись земли. Запрограммировали так, что когда шасси начинают крутиться, то закрылки ставим в положение «торможение». Но вот во время испытаний в Варшаве самолет выкатился за пределы полосы, так как была мокрая поверхность. Он проскользил, только потом был крутящий момент и они, закрылки, открылись. С точки зрения «верификации» — программа сработала, с точки зрения «валидации» — нет. Поэтому код изменили так, чтобы в момент изменения давления в шинах открывались закрылки.
Документацию, которая используется на проектах по разработке ПО, можно условно разделить на две группы:
Этапы тестирования:
Стадии разработки ПО — этапы, которые проходят команды разработчиков ПО, прежде чем программа станет доступной для широкого круга пользователей.
Требования
Требования — это спецификация (описание) того, что должно быть реализовано.
Требования описывают то, что необходимо реализовать, без детализации технической стороны решения.
Дефект (bug) — отклонение фактического результата от ожидаемого.
Отчёт о дефекте (bug report) — это документ, описывающий ситуацию, которая привела к обнаружению дефекта, с указанием причин и ожидаемого результата.
Жизненный цикл бага
Severity vs Priority
Серьёзность (severity) показывает степень ущерба, который наносится проекту существованием дефекта. Severity выставляется тестировщиком.
Срочность (priority) показывает, как быстро дефект должен быть устранён. Priority выставляется менеджером, тимлидом или заказчиком
Тестовые среды
Основные фазы тестирования
Основные виды тестирования ПО
Вид тестирования — это совокупность активностей, направленных на тестирование заданных характеристик системы или её части, основанная на конкретных целях.
Тест-дизайн — это этап тестирования ПО, на котором проектируются и создаются тестовые случаи (тест-кейсы).
Типы тестирования
Тестирование белого ящика — метод тестирования ПО, который предполагает, что внутренняя структура/устройство/реализация системы известны тестировщику.
Согласно ISTQB, тестирование белого ящика — это:
– тестирование, основанное на анализе внутренней структуры компонента или системы;
– тест-дизайн, основанный на технике белого ящика — процедура написания или выбора тест-кейсов на основе анализа внутреннего устройства системы или компонента.
Почему «белый ящик»? Тестируемая программа для тестировщика — прозрачный ящик, содержимое которого он прекрасно видит.
Тестирование серого ящика — метод тестирования ПО, который предполагает комбинацию White Box и Black Box подходов. То есть, внутреннее устройство программы нам известно лишь частично.
Тестирование чёрного ящика — также известное как тестирование, основанное на спецификации или тестирование поведения — техника тестирования, основанная на работе исключительно с внешними интерфейсами тестируемой системы.
Согласно ISTQB, тестирование черного ящика — это:
– тестирование, как функциональное, так и нефункциональное, не предполагающее знания внутреннего устройства компонента или системы;
– тест-дизайн, основанный на технике черного ящика — процедура написания или выбора тест-кейсов на основе анализа функциональной или нефункциональной спецификации компонента или системы без знания ее внутреннего устройства.
Тестовая документация
Тест план (Test Plan) — это документ, описывающий весь объем работ по тестированию, начиная с описания объекта, стратегии, расписания, критериев начала и окончания тестирования, до необходимого в процессе работы оборудования, специальных знаний, а также оценки рисков с вариантами их разрешения.
Основные пункты тест плана:
В стандарте IEEE 829 перечислены пункты, из которых должен состоять тест-план:
a) Идентификатор тест плана (Test plan identifier);
b) Введение (Introduction);
c) Объект тестирования (Test items);
d) Функции, которые будут протестированы (Features to be tested;)
e) Функции, которые не будут протестированы (Features not to be tested);
f) Тестовые подходы (Approach);
g) Критерии прохождения тестирования (Item pass/fail criteria);
h) Критерии приостановления и возобновления тестирования (Suspension criteria and resumption requirements);
i) Результаты тестирования (Test deliverables);
j) Задачи тестирования (Testing tasks);
k) Ресурсы системы (Environmental needs);
l) Обязанности (Responsibilities);
m) Роли и ответственность (Staffing and training needs);
n) Расписание (Schedule);
o) Оценка рисков (Risks and contingencies);
p) Согласования (Approvals).
Чек-лист (check list) — это документ, который описывает что должно быть протестировано. Чек-лист может быть абсолютно разного уровня детализации.
Чаще всего чек-лист содержит только действия, без ожидаемого результата. Чек-лист менее формализован.
Тестовый сценарий (test case) — это артефакт, описывающий совокупность шагов, конкретных условий и параметров, необходимых для проверки реализации тестируемой функции или её части.
BFT – Потоковое тестирование
Добрый день, Хаброчитатели!
Потоковое тестирование (BFT — BusinessFlowTesting)
BFT Framework
Как же устроен BFT фреймворк и как его сделать самому? Рассмотрим простой пример
Допустим, ваше приложение – магазин, продающий товары. Основными Приемочными тестами будут тесты на то, как пользователь приобретает этот товар и что с ним может случится дальше.
Каждый тест — это линейный путь в этом графе, который характеризуется входными данными.
Написание тестов
Базовый простой тест
У нас есть бизнес модель-граф. Для этого графа мы создаем тестовый код, который описывает, уже на языке программирования, то что надо проверять в каждом состоянии и куда идти дальше.
Итог: у нас описан тестовый граф (граф вначале не обязательно описывать полностью, допустим, вначале описан только позитивный сценарий, все остальные состояния и переходы можно добавлять по мере необходимости).
Первый тест – это обычно главный позитивный тест, который проходит от начала бизнес потока и до конца без ошибок.
Формируем входные данные для позитивного теста.
Сам тест будет выглядеть примерно так:
var SimpleScenario = BusinessGraph.GetScenario(CorrectSimpleData, DefaultControllData);BFTFramework.Run(SimpleScenario, CorrectSimpleData);
BusinessGraph по входным данным CorrectSimpleData построит линейный путь-сценарий (по умолчанию DefaultControllData) в графе на выходе получаем SimpleScenario.
BFTFramework исполнит этот сценарий со входными данными CorrectSimpleData.
Остальные тесты
Теперь, если мы хотим проверить много разных позитивных данных, то просто передаем другие наборы CorrectOtherData.
Итого:
Область применения
Test Design Techniques overview
Quality Assurance Engineer
The main idea is to walk through the Test Design techniques. As a starting point, I chose the list from ISO/IEC/IEEE 29119-4 Test Techniques.
Why TDt and why do we need another article about it? Because TDt is all about testing, or almost all. And because a short overview of all techniques will be useful as a reference for picking the appropriate method for your tasks.
Of course, the techniques are not a silver bullet, they do not magically turn specification or code into test cases. You still need to analyze each functionality aspect very carefully, and choose and apply the techniques wisely.
But they definitely help. Some of them simply reduce the number of cases from hundreds to dozens, or from hundreds of thousands to hundreds. Some can help to organize and visualize key aspects of the functionality. The clearer picture you have on your notes/monitor, the clearer picture you get in your mind and the less possibility to overlook something valuable.
Table of Contents
Specification-Based Testing Techniques
All the specification-based or Black Box testing techniques may be conveniently described and systematized with the following table:
Group | Technique | Use when |
Elementary Techniques: — focused on analysing the input/output parameters — can be combined for providing better coverage — usually do not use and do not depend on the other techniques | Equivalence Partitioning | Input and output parameters have a large number of possible values |
Boundary Value Analysis | Parameter values have explicit (e.g. clearly defined in documentation) boundaries and ranges, or implicit (e.g. known technical limitations) boundaries | |
Combinatorial strategies: — combine possible values of multiple input/output parameters — can use elementary techniques to reduce the number of possible values | All Combinations | The number of possible input combinations is reasonably small, or each separate combination of inputs leads to a specific output |
Pairwise Testing | The number of input combinations is extremely large and should be reduced to an acceptable set of cases | |
Each Choice Testing | You have functionality where a specific parameter value rather cause an error than a combination of values | |
Base Choice Testing | You can distinguish a set of parameter values that has the highest probability of being used | |
Advanced techniques: — help to analyze the System from the perspective of the business logic, hierarchical relations, scenarios, etc. — analysis is based on data organized in tables, diagrams and templates — can rely on elementary and combinatorial techniques for designing test cases | Decision Table Testing | There is a set of parameter combinations and their outputs described by business or other rules |
Classification Tree Method | You have hierarchically structured data, or data can be represented in a form of a hierarchical tree | |
State Transition Testing | There are obvious states in the functionality that have transitions regulated by rules (e.g. flows) | |
Cause-Effect Graphing | Causes (inputs) and effects (outputs) are connected by the large number of complex logical dependencies | |
Scenario Testing | There are clear scenarios in the functionality | |
Other | Random Testing | You need to emulate the unpredictability of real-life inputs, or functionality has non-systematic defects |
Syntax Testing | A functionality has a complex syntax format for inputs (e.g. codes, complex email names, etc.) |
As you can see, the table shows when the techniques can be used, and also generalizes which techniques may rely on others. Now, let’s have a closer look at each of them.
Equivalence Partitioning
A well known technique and one of the most used. Often you can find an explanation like this:
It is a very simple and understandable explanation, but it may give a narrow view on this technique. What if we do not have a range of numbers?
The Equivalence Partitioning concept came from maths and understanding what Equivalence Class and Equivalence relation are, which might be difficult to grasp quickly without a maths background. But for testing purposes, I think, it can be simplified by defining it as this:
An Equivalence partition is a subset of elements from a specific set, which are treated by the System (under test) in the same way. So you don’t need to perform tests for each element of the subset and just one check is enough to cover the whole subset. Therefore, the technique can be described as dividing of the whole set of input/output data into such partitions. And if you have, for example, a set of data with about 100 elements which can be divided into 5 partitions, you can decrease the number of cases to 5.
A very effective, time saving technique.
Boundary Value Analysis
And the common formula by Coupland’s Guide is just to check
where x is a boundary value, and step is a minimal decrement/increment (e.g. 1 for integers, 0.01$ for prices).
But I find this description a bit ambiguous (because of three values here), and prefer the explanation which says that for checking boundaries we should check the valid edge values of a range, plus one value beneath and one value beyond the range. So for the range more than 1 and less or equal to 10, these are 1, 2 and 10, 11:
and even if the developer made a serious mistake and wrote something like this:
even so, if we combine boundary values with an equivalence classes check, we don’t miss this mistake:
This technique seems fairly easy, but sometimes you can overlook boundaries because they are not so obvious. Don’t miss partitions (e.g. out of valid range), don’t miss sequences and open boundaries, choose the right «step» and this simple technique will save you plenty of time.
Combinatorial Test Techniques
Or rather consider them as combinatorial strategies. Their main purpose is to produce combinations of input parameters basing on one of the algorithms below.
All Combinations
As we can see from the title, this algorithm implies generation of every possible combination. This means exhaustive testing and makes sense only if the number of combinations is reasonable. For example, 3 variables with 3 values for each give us a 3×3 matrix of parameters with 27 possible combinations.
Pairwise Testing
But what if we have, for example, 10 variables? Even if they are boolean, we get 2^10 = 1024 combinations. If you increase the number of parameters, you get an increase in the number of combinations as a power function. And if you increase the number of variables, you get an exponential increase in the number of combinations. What can we do if the number of combinations is somewhere in the hundreds of thousands? Pairwise Testing or «all pairs» algorithm will help us significantly decrease the number of combinations and still get robust test coverage. It relies on two principles:
Thus we just need to identify all unique pairs from our parameters, and then build our test cases by trying to make unique combinations of pairs.
param1 | param2 | param3 |
a | 1 | X |
b | 2 | Y |
c | 3 | Z |
a 1 | 1 X | a X |
a 2 | 2 Y | a Y |
a 3 | 3 Z | a Z |
b 1 | 1 Z | b Z |
b 2 | 2 X | b X |
b 3 | 3 Y | b Y |
c 1 | 1 Y | c Y |
c 2 | 2 Z | c Z |
c 3 | 3 X | c X |
and we can combine the first and the second columns and skip the third as redundant (as the first and second columns already contain the combinations from the third one):
Test Case | param1 | param2 | param3 |
1 | a | 1 | X |
2 | a | 2 | Y |
3 | a | 3 | Z |
4 | b | 1 | Z |
5 | b | 2 | X |
6 | b | 3 | Y |
7 | c | 1 | Y |
8 | c | 2 | Z |
9 | c | 3 | X |
Now we’ve got only 9 cases instead of 27.
Of course, this is not very easy to do even if you have just a few parameters. So, for solving this task, there are plenty of tools that generate the required combinations automatically. The only thing that is left to you is to thoroughly examine and setup all the settings provided by your tool, and then do a couple of test runs with a small manageable set of data to make sure your tool is configured correctly and create proper combinations.
If you want to dive deeper into this:
Each Choice Testing
This strategy means that each value of each particular parameter must be used at least once in a test set. So the resulting number of cases will be equal to the number of values of the parameter with the biggest range. Each choice is a minimal coverage strategy.
Test Case | param1 | param2 | param3 |
1 | a | 1 | X |
2 | b | 2 | Y |
3 | c | 3 | X |
4 | a | 4 | Y |
5 | b | 5 | X |
Base Choice Testing
Test Case | param1 | param2 | param3 |
1 | a | 2 | Y |
2 | b | 2 | Y |
3 | c | 2 | Y |
4 | a | 1 | Y |
5 | a | 3 | Y |
6 | a | 2 | X |
7 | a | 2 | Z |
Decision Table Testing
This simple technique consists in documenting business logic in a table as sets of conditions and actions. For example, if you have a set of variables which are hard to remember and manage, a Decision Table will help to organize them to simplify identification of the right cases.
Rule/Test Case 1 | Rule/Test Case 2 | Rule/Test Case 3 | . | |
Conditions | role | guest | admin | user |
location | UK | US | US | |
site section | admin section | admin section | user section | |
Actions | «This page isn’t available for your location» | — | ✔ | — |
«You don’t have enough rights to view the page» | ✔ | — | — | |
Success: the page is displayed | — | — | ✔ |
Although the decision table technique gives you less visibility than the techniques based on drawing diagrams, it works perfectly for simple cases. And for complex cases, the decision table is used as a final step of data conversion. All this makes it the «must know» method for designing test cases.
Classification Tree Method
Most of the resources distinguish two main steps for this technique:
Both these steps are fair for most of the testing techniques, and can be rephrased as:
— identify input/output parameters, and then combine them to get your cases
Now let’s add some details.
A Classification Tree is a graphical technique which helps us to visualize test-relevant aspects (aspects that affect the behavior of the test object during the test) in the form of a hierarchical tree.
How to grow this tree. It looks similar to mind maps with slight differences if it gives you a hint. We have a test object (whole app, a particular feature, an abstract idea, etc.) on the top as a root. We draw branches from the root as classifications (test relevant aspects which we identified). Then, using equivalence partitioning and boundary value analysis, we define our leaves as classes from the range of all possible values for a particular classification. And if some of the classes can be classified further, we draw sub-branch/classification with own leaves/classes. When our tree is complete, we make projections of the leaves on a horizontal line (a test case) using one of the combinatorial strategies (all combinations, each choice, etc.), and create all the required combinations.
In the example above, the «Each Choice» combinatorial strategy was used.
Of course, there is much more detail in this technique and if you are interested in this method, you can find useful information in the following sources:
The most obvious advantages for me here is a great visibility and clearness of the test object scope and test case ideas. If you have some complex, hierarchy-structured data and you can afford to spend time on creating and supporting the tree, I think this technique will be extremely handy. And, to effectively apply the method, you might consider using a special tool, like Classification Tree Editor.
State Transition Testing
Another graphical/table technique which is convenient to use when your target functionality is a System with a finite number of states and transitions between them (flows, all kind of «masters» etc.), and where transitions are defined by some set of rules.
The technique is to draw all transitions one by one on a diagram. Like in the popular example with PIN checking below:
After we have visualized all transitions, we just execute particular paths from the diagram as test cases:
Cause-Effect Graphing
Cause-effect graphing is similar to a Decision Table and also uses the idea of combining conditions. And sometimes they are described as one method. But if there are a lot of logical dependencies between conditions, it may be easier to visualize them on a cause-effect graph.
Here, we can distinguish three stages:
To explain this particular techique, we should review a lot of conventional notations that go beyond the scope of this post. Nevertheless, this is an interesting topic which I will get back to in my next publications.
Scenario Testing (including Use Case Testing)
As a rule, a test case is represented by a very few actions and a single result. Scenario, on the other hand, is a sequence of actions (with intermediate results) that lead to accomplishing some specific goal. Scenarios can be a part of a developer’s documentation (scenario diagrams). Quite often they are documented in requirements as «Use Cases» — scenarios that usually describe user interactions with the System.
But often these scenarios are not very detailed. Also, before using them for creating test cases, they need to be thoroughly described using a template. Templates can vary from project to project. But among such usual fields like name, goal, preconditions, actor(s) etc., there are always: the main successful scenario and so-called extensions (plus sometimes sub-variations). Extensions are the conditions that affect the main success scenario. And sub-variations are the conditions that do not impact the main flow, but still should be considered.
After the template is filled with data, we create specific test cases using equivalence partitioning and boundary values techniques. For minimal coverage, we need at least one test case for the main success scenario and at least one test case for each extension.
Again, this technique fits the common formula «get conditions that vary our output, and check combinations». But the way to get those is to analyze the behavior of the System through scenarios.
Random Testing
Also known as random-input testing, this is probably the most misjudged technique, the main idea of which is to choose random inputs from the possible values for particular functionality. So there isn’t any system in choosing input data. This technique is also called «monkey» testing, and if we are speaking about manual testing, I assume that it can be less effective than other black box techniques.
But if we add automation, it becomes a powerful instrument. Just imagine that test cases (with distinct sets of inputs) are generated, executed and evaluated automatically in a continuous cycle, allowing you to run thousands and millions of cases within a reasonable time.
Creating a «Random Tester» is a quite an interesting topic, but also quite complex and requires deeper study. Here, I describe it only conceptually.
Using a pseudo-random generator with the seed is convenient as we can re-generate all suits of cases for a particular seed. Cases are generated based on the domain knowledge. Then they are executed in our system under a test environment. After that, «Oracle» (a special instrument) verifies outputs and if we’ve got an output different from what we expected, we save the test case and continue the cycle.
The most complex and challenging part here is to create Random Test Case generator and Oracle. From the resources I found, the next course gives a reasonable explanation of the topic.
Syntax Testing
This technique helps with designing test cases for input formats. Of course, if our syntax rules sound like «there should be only digits or letters», we don’t need this technique. But if we have some complex format (e.g. postcode, phone, specific email address) it may be handy.
First of all, we should identify our format and describe it formally using the Backus-Naur Form (or Extended BNF). This is a crucial point, so I would suggest you get acquainted with BNF before reading further. I won’t explain BNF here, but you can find pretty good explanation about what BNF is in Wikipedia.
After we created the BNF definition for our format, it is time to generate positive and negative cases:
You can find a very detailed example of positive and negative cases by following the link below:
Structure-Based Testing Techniques
Also known as White Box testing techniques, this means that we are familiar with the code we are going to test. In order to understand these techniques, we should define what the coverage is in a test design context. Here is a good definition from ISTQB Book:
Test coverage measures in some specific way the amount of testing performed by a set of tests (derived in some other way, e.g. using specification-based techniques). Wherever we can count things and can tell whether or not each of those things has been tested by some test, then we can measure coverage. The basic coverage measure is
where the ‘coverage item‘ is whatever we have been able to count and see whether a test has exercised or used this item.
For specification-based techniques, it can be use cases, equivalence partitions, boundary values, states from a state-transition diagram, a percentage of business rules from a decision table, etc. For structure-based techniques, coverage items are represented by the structural elements of a code.
In principle, coverage evaluation means that we should decide which structural elements we are going to use (e.g. statements or decisions). Then, find the total number of these elements in the code. Inject additional statements (for example logging) alongside each structural element in order to find out whether the element was exercised during the test case execution. And finally, measure the coverage by executing the tests and using the formula mentioned above. But, as a rule, you shouldn’t think about all these steps because there are a lot of automated tools for measuring the coverage.
Structure-Based Testing techniques usually imply that you should measure the coverage for existing test sets (including black-box sets), and then design additional white-box test cases that are based on structural code elements to achieve the most optimal coverage possible.
Statement Testing
It is the lowest coverage level when the «statement» is chosen as the coverage item. The statement is an entity in a programming language, which is typically the smallest indivisible unit of execution. These examples should give you an idea:
Let’s take a look at a simple example from Copeland’s «A Practitioner’s Guide to Software Test Design»:
This way, this coverage level cannot be considered as sufficient.
Decision Testing
A «decision» is a program point at which the control flow has two or more alternative routes. The control flow is a sequence of events (paths) in the execution through a component or system. So, to be exact, a «decision» is a control flow node (like if statement, loop statement, or case statement) which have two or more links to separate execution branches.
The 100% decision coverage means that all possible decision outcomes were exercised at least once. For if statements, these are true or false. If we look back at our previous example, we will require more tests to get 100% decision coverage (at least two more a and a > 0 and b == 3 to cover both decisions, and get true and false outcomes).
This example shows that decision coverage is ‘stronger’ than statement coverage (because it requires more checks which can find more bugs). And also that the 100% decision coverage always guarantees 100% statement coverage.
Condition Testing
Branch Condition Testing
Branch Condition testing aims to test each outcome of the particular logical condition. Let’s add a few conditions to our example and simplify them to a, b, c and d:
Here we still have two decision points and 4 possible outcomes. But from the conditions perspective, there will be 4 conditions and 8 possible outcomes. These outcomes can be covered with two cases:
I think it is obvious that if we select the following values for the conditions a and b in these test cases:
We will still have the 100% coverage for branch condition method, but we will never reach the expression 1.
As you can see from this example, for the optimal results, the best strategy is to always aim for 100% Condition/Decision coverage.
Branch Condition Combination Testing
Branch Condition testing is a stronger strategy than Decision testing, but still the 100% branch condition coverage doesn’t cover all the paths. We cover all the paths only if we execute all possible combinations of conditions. This approach is called Branch Condition Combination Testing.
If we recall combinatorial techniques from Specification-Based group, then for a boolean parameter we get 2 n combinations (where n is a number of conditions). So for our example, there will be 16 possible combinations/cases which cover all the possible paths of our control flow. Obviously this approach leads to exhaustive testing.
Modified Condition Decision Coverage (MCDC) Testing
Branch condition testing is too little, Branch Condition Combination is too much. So what is in the middle?
The MCDC technique that states that test cases should be designed in a way when each single condition in a decision should affect the decision’s outcome independently. This means, if we are going to test a condition, we should not use the values for other conditions that mask this condition results. For example:
if a = false, the decision outcome will always be false, so it will mask results for b.
Now let’s design tests for a slightly more complex example:
According to coverage rule, there will be the next cases:
Case | a | b | c | decision outcome |
a1 | false | true | false | false |
a2 | true | true | false | true |
b1 | true | true | false | true |
b2 | true | false | false | false |
c1 | true | false | false | false |
c2 | true | false | true | true |
Conditions marked with grey color were selected in a way that allowed not to mask the effect from a target condition. If we look closely at the table, we will see that a2 equals to b1 and b2 equals to c1. This reduces our table to only 4 cases:
Case | a | b | c | decision outcome |
a1 | false | true | false | false |
a2, b1 | true | true | false | true |
b2, c1 | true | false | false | false |
c2 | true | false | true | true |
Data Flow Testing:
Data Flow Testing is another set of white box techniques/strategies that is related to analyzing the control flow, but in terms of the variable’s life cycle. Variables are defined, used and killed when there is no further need of them. Anomalies in this process, such as using a variable without defining it or after it has been killed, could lead to an error.
There are conventional notations which can help to describe time-sequenced pairs in the life cycle of the variable:
are perfectly valid combinations, when
are anomalies, potential or explicit bugs. Currently, practically all of them are efficiently detected by compilers, or at least IDEs, and we rarely need to perform static analysis for detecting these anomalies.
The same is true for the dynamic analysis that is focused on du pairs exploration/execution — modern programming languages reduce the probability of du-related issues. So, currently, such verification is mostly not worth the effort. If you still interested in the topic you can find more information here:
Experience-Based Testing Techniques
Error Guessing
The least formal technique of all, and for many people it might be just a matter of course, like «be a QA and use your experience». So there are no particular steps or rules which can help you to design test cases. Just a reminder to always think about error possibilities and weaknesses even when the other more formal techniques are already applied.