Метод комбинаторного покрытия условий

Критерий комбинаторного покрытия условий удовлетворяет также и критериям покрытия решений, покрытия условий и по­крытия решений/условий.

Этот метод требует создания такого числа тестов, чтобы все возможные комбинации результатов условия в каждом решении выполнялись по крайней мере один раз. По этому критерию в рассматриваемом примере должны быть покрыты тестами сле­дующие восемь комбинаций:

 

1.A>1,B=0. 5.А = 2,Х>1.

2. A > 1,B<>0. 6.А = 2,Х<1.

З.A<1,B=0. 7.А<>2,Х>1.

4.A<1,B<>0. 8.A<>2,X<1.

Для того чтобы протестировать эти комбинации, необяза­тельно использовать все 8 тестов. Фактически они могут быть покрыты четырьмя тестами (табл. JI5.4):

А = 2, B= 0, Х= 4 {покрывает 1, 5};

А = 2, B= 1, Х= 1 {покрывает 2, 6};

А = 0,5, B = 0, Х= 2 {покрывает 3, 7};

A=1,B=0, Х= 1 {покрывает 4, 8}.

Таблица Л5.4.

Результаты тестирования методом комбинаторного покрытия условий

Тест Ожидаемый результат Фактический результат Результат тестирования
A = 2, В=0,Х=4 Х=3 Х=3 Неуспешно
A= 2, В=1,Х=1 Х=2 Х= 1,5 Успешно
A = 0,5, b=0,x=2 X=3 Х=4 Успешно
A=1, В=0,Х= 1 X=1 X=1 Неуспешно

Функциональное тестирование или тестирование по методом четного ящика базируется на том, что все тесты основаны на спецификации системы или ее компонентов. Поведение системы определяется изучением ее входных и соответствующих выходных данных.

При тестировании «черного ящика» тестировщик имеет доступ к ПО только через те же интерфейсы, что и заказчик или пользователь, либо через внешние интерфейсы, позволяющие другому компьютеру либо другому процессу подключиться к системе для тестирования. Например, тестирующий модуль может виртуально нажимать клавиши или кнопки мыши в тестируемой программе с помощью механизма взаимодействия процессов с уверенностью в том, что эти события вызывают тот же отклик, что и реальные нажатия клавиш и кнопок мыши.

Методология составления тестов "чёрного ящика"

· Эквивалентное разбиение

· Анализ граничных значений

· Применение функциональных диаграмм

· Предположение об ошибке

Эквивалентное разбиение

Тестирование программы ограничивается использованием небольшого подмножества всех возможных входных данных. Тогда, конечно, хотелось бы выбрать для тестирования самое подходящее подмножество (т. с. подмножество с наивысшей вероятностью обнаружения большинства ошибок). Правильно выбранный тест этого подмножества должен обладать двумя свойствами:

· уменьшать, причем более чем на единицу, число других тестов, которые должны быть разработаны для достижения заранее определенной цели "приемлемого" тестирования;

· покрывать значительную часть других возможных тестов, что в некоторой степени свидетельствует о наличии или отсутствии ошибок до и после применения этого ограниченного множества значений входных данных.

Указанные свойства, несмотря на их кажущееся подобие, описывают два различных положения. Во-первых, каждый тест должен включать столько различных входных условий, сколько это возможно, с тем, чтобы минимизировать общее число необходимых тестов. Во-вторых, необходимо пытаться разбить входную область программы на конечное число классов эквивалентности так, чтобы можно было предположить (конечно, не абсолютно уверенно), что каждый тест, являющийся представителем некоторого класса, эквивалентен любому другому тесту этого класса. Иными словами, если один тест класса эквивалентности обнаруживает ошибку, то следует ожидать, что и все другие тесты этого класса эквивалентности будут обнаруживать ту же самую ошибку. Наоборот, если тест не обнаруживает ошибки, то следует ожидать, что ни один тест этого класса эквивалентности не будет обнаруживать ошибки (в том случае, когда некоторое подмножество класса эквивалентности не попадает в пределы любого другого класса эквивалентности, так как классы эквивалентности могут пересекаться). Эти два положения составляют основу методологии тестирования по принципу черного ящика, известной как эквивалентное разбиение. Второе положение используется для разработки набора "интересных" условий, которые должны быть протестированы, а первое - для разработки минимального набора тестов, покрывающих эти условия. Примером класса эквивалентности для программы о треугольнике является набор "трех равных чисел, имеющих целые значения, большие нуля". Определяя этот набор как класс эквивалентности, устанавливают, что если ошибка не обнаружена некоторым тестом данного набора, то маловероятно, что она будет обнаружена другим тестом набора. Иными словами, в этом случае время тестирования лучше затратить на что-нибудь другое (на тестирование других классов эквивалентности). Разработка тестов методом эквивалентного разбиения осуществляется в два этапа:

1. выделение классов эквивалентности

2. построение тестов.

Выделение классов эквивалентности

Классы эквивалентности выделяются путем выбора каждого входного условия (обычно это предложение или фраза в спецификации) и разбиением его на две или более групп.

Заметим, что различают два типа классов эквивалентности: правильные классы эквивалентности, представляющие правильные входные данные программы, и неправильные классы эквивалентности, представляющие все другие возможные состояния условий (т. е. ошибочные входные значения). При этом существует ряд правил:

1. Если входное условие описывает область значений (например, "целое данное может принимать значения от 1 до 999"), то определяются один правильный класс эквивалентности (1 <= значение целого данного <= 999) и два неправильных (значение целого данного < 1 и значение целого данного > 999).

2. Если входное условие описывает множество входных значений и есть основание полагать, что каждое значение программа трактует особо (например, "известны способы передвижения на АВТОБУСЕ, ГРУЗОВИКЕ, ТАКСИ, ПЕШКОМ или МОТОЦИКЛЕ"), то определяется правильный класс эквивалентности для каждого значения и один неправильный класс эквивалентности (например, "НА ПРИЦЕПЕ").

3. Если входное условие описывает ситуацию "должно быть" (например, "первым символом идентификатора должна быть буква"), то определяется один правильный класс эквивалентности (первый символ - буква) и один неправильный (первый символ - не буква).

4. Если есть любое основание считать, что различные элементы класса эквивалентности трактуются программой неодинаково, то данный класс эквивалентности разбивается на меньшие классы эквивалентности.

Построение тестов

Второй шаг заключается в использовании классов эквивалентности для построения тестов. Этот процесс включает в себя:

1. Назначение каждому классу эквивалентности уникального номера.

2. Проектирование новых тестов, каждый из которых покрывает как можно большее число непокрытых правильных классов эквивалентности, до тех пор, пока все правильные классы эквивалентности не будут покрыты (только не общими) тестами.

3. Запись тестов, каждый из которых покрывает один и только один из непокрытых неправильных классов эквивалентности, до тех пор, пока все неправильные классы эквивалентности не будут покрыты тестами. Причина покрытия неправильных классов эквивалентности индивидуальными тестами состоит в том, что определенные проверки с ошибочными входами скрывают или заменяют другие проверки с ошибочными входами. Например, спецификация устанавливает "тип книги при поиске (ВЫЧИСЛИТЕЛЬНАЯ ТЕХНИКА, ПРОГРАММИРОВАНИЕ или ОБЩИЙ) и количество (1-9999)". Тогда тест XYZ O отображает два ошибочных условия (неправильный тип книги и количество) и, вероятно, не будет осуществлять проверку количества, так как программа может ответить: "XYZ-НЕСУЩЕСТВУЮЩИЙ ТИП КНИГИ" и не проверять остальную часть входных данных.

Пример

Предположим, что при разработке компилятора для подмножества языка программирования требуется протестировать синтаксическую проверку оператора DIM[l].

Пусть определена следующая спецификация:

Оператор DIM используется для определения массивов.

DIM ad [, ad]…,где ad есть описатель массива в форме n(d[,d]...), п – символическое имя массива, а d – индекс массива.

Символические имена могут содержать от одного до шести символов - букв или цифр, причем первой должна быть буква.

Допускается от одного до семи индексов. Форма индекса [lb:] ub, где lb и ub задают нижнюю и верхнюю границы индекса массива. Граница может быть либо константой, принимающей значения от - 65534 до 65535, либо целой переменной (без индексов). Если lb не определена, то предполагается, что она равна единице. Значение ub должно быть больше или равно lb. Если lb определена, то она может иметь отрицательное, нулевое или положительное значение. Оператор модет распологатьсяна нескольких строках (Конец спецификации.)

Первый шаг заключается в том, чтобы идентифицировать входные условия и по ним определить классы эквивалентности. Классы эквивалентности в таблице обозначены числами.

Входные условия Правильные классы эквивалентности Неправильные классы эквивалентности
Число описателей массивов ОДИН (1), > ОДНОГО (2) НИ ОДНОГО (3)
Длина имени массива 1-6(4) 0(5), > 6(6)
Имя массива Имеет в своем составе буквы (7) и цифры (8) содержит что-то еще (9)
Имя массива начинается с буквы да (10) нет (11)
Число индексов 1-7(12) 0(13), > 7(14)
Верхняя граница Константа (15), целая переменная (16) имя элемента массива (17), что-то иное (18)
Имя целой переменной Имеет в своем составе буквы (19), и цифры (20) состоит из чего-то еще (21)
Целая переменная начинается с буквы да (22) нет (23)
Константа От -65534 до 65535 (24)) Меньше -65534 (25), больше 65535 (26)
Нижняя граница определена да (27), нет (28)  
Верхняя граница по отношению к нижней границе Больше (29), равна (30) меньше (31)
Значение нижней границы Отрицательное (32) Нуль (33), > 0 (34)  
Нижняя граница Константа (35), целая переменная (36) имя элемента массива (37), что-то иное (38)
Оператор расположен на нескольких строках да (39), нет (40)  

Следующий шаг - построение теста, покрывающего один или более правильных классов эквивалентности.

Например, тест DIM A(2) покрывает классы 1, 4, 7, 10, 12, 15, 24, 28, 29 и 40.

Далее определяются один или более тестов, покрывающих оставшиеся правильные классы эквивалентности.

Так, тест

DIM A12345(I,9,J4XXXX.65535,1,KLM, X 100),

ВВВ (-65534 : 100,0 : 1000,10 : 10,1 : 65535)

покрывает оставшиеся классы.

Перечислим неправильные классы эквивалентности и соответствующие им тесты:

(3) DIMENSION
(5) DIMENSION(10)
((6) DIMENSION A234567(2)
(9) DIMENSION A.I(2)
(11) DIMENSION1A(10)
(13) DIMENSION В
(14) DIMENSION В (4,4,4,4,4,4,4,4)
(17) DIMENSION В(4,А(2))
(18) DIMENSION В(4„7)
(21) DIMENSION С(1.,10)
(23) DIMENSION C(10,1J)
(25) DIMENSION D (-65535:1)
(26) DIMENSION D(65536)
(31) DIMENSION D(4:3)
(37) DIMENSION D(A(2):4)
(38) DIMENSION D(.:4)

Эти классы эквивалентности покрываются 18 тестами.

Хотя эквивалентное разбиение значительно лучше случайного выбора тестов, оно все же имеет недостатки (т. е. пропускает определенные типы высокоэффективных тестов).

Следующие два метода - анализ граничных значений и использование функциональных диаграмм (диаграмм причинно-следственных связей cause-effect graphing) - свободны от многих недостатков, присущих эквивалентному разбиению.

 

Анализ граничных значений

Как показывает опыт, тесты, исследующие граничные условия, приносят большую пользу, чем тесты, которые их не исследуют. Граничные условия - это ситуации, возникающие непосредственно на, выше или ниже границ входных и выходных классов эквивалентности. Анализ граничных значений отличается от эквивалентного разбиения в двух отношениях:

1. Выбор любого элемента в классе эквивалентности в качестве представительного при анализе граничных значений осуществляется таким образом, чтобы проверить тестом каждую границу этого класса.

2. При разработке тестов рассматривают не только входные условия (пространство входов), но и пространство результатов (т. е. выходные классы эквивалентности) .

Приведем несколько общих правил этого метода.

1. Построить тесты для границ области и тесты с неправильными входными данными для ситуаций незначительного выхода за границы области, если входное условие описывает область значений. Например, если правильная область входных значений есть - 1,0 - +1,0, то написать тесты для ситуаций - 1,0, 1,0, - 1,001 и 1,001.

2. Построить тесты для минимального и максимального значений условий и тесты, большие и меньшие этих значений, если входное условие удовлетворяет дискретному ряду значений. Например, если входной файл может содержать от 1 до 255 записей, то получить тесты для 0,1, 255 и 256 записей.

3. Использовать правило 1 для каждого выходного условия. Например, если программа вычисляет ежемесячный расход и если минимум расхода составляет 0,00 дол., а максимум - 1165,25 дол., то построить тесты, которые вызывают расходы с 0,00 дол. и 1165,25 дол. Кроме того, построить, если это возможно, тесты, которые вызывают отрицательный расход и расход больше 1165,25 дол. Заметим, что важно проверить границы пространства результатов, поскольку не всегда границы входных областей представляют такой же набор условий, как и границы выходных областей (например, при рассмотрении подпрограммы вычисления синуса). Не всегда также можно получить результат вне выходной области, но, тем не менее, стоит рассмотреть эту возможность.

4. Использовать правило 2 для каждого выходного условия. Например, если система информационного поиска отображает на экране терминала наиболее релевантные рефераты в зависимости от входного запроса, но никак не более четырех рефератов, то построить тесты, такие, чтобы программа отображала нуль, один и четыре реферата, и тест, который мог бы вызвать выполнение программы с ошибочным отображением пяти рефератов.

5. Если вход или выход программы есть упорядоченное множество (например, последовательный файл, линейный список, таблица), то сосредоточить внимание на первом и последнем элементах этого множества.

Существенное различие между анализом граничных значений и эквивалентным разбиением заключается в том, что анализ граничных значений исследует ситуации, возникающие на и вблизи границ эквивалентных разбиений.

Пример

Положим, что нужно протестировать программу бинарного поиска. Нам известна спецификация этой программы. Поиск выполняется в массиве элементов М, возвращается индекс I элемента массива, значение которого соответствует ключу поиска Key.

Входные условия:

1) массив должен быть упорядочен;

2) массив должен иметь не менее одного элемента;

3) нижняя граница массива (индекс) должна быть меньше или равна его верхней границе.

Результаты::

1) если элемент найден, то флаг Result=True, значение I — номер элемента;

2) если элемент не найден, то флаг Result=False, значение I не определено.

Для формирования классов эквивалентности (и их ребер) надо построить дерево разбиений. Листья дерева разбиений дадут нам искомые классы эквивалентности. Определим стратегию разбиения. На первом уровне будем анализировать выполнимость входных условий, на втором уровне — выполнимость результатов. На третьем уровне можно анализировать специальные требования, полученные из практики разработчика. В нашем примере мы знаем, что входной массив должен быть упорядочен. Обработка упорядоченных наборов из четного и нечетного количества элементов может выполняться по-разному. Кроме того, принято выделять специальный случай одноэлементного массива. Следовательно, на уровне специальных требований возможны следующие эквивалентные разбиения:

1) массив из одного элемента;

2) массив из четного количества элементов;

3) массив из нечетного количества элементов, большего единицы.

Наконец на последнем, 4-м уровне критерием разбиения может быть анализ ребер классов эквивалентности. Очевидно, возможны следующие варианты:

1) работа с первым элементом массива;

2) работа с последним элементом массива;

3) работа с промежуточным (ни с первым, ни с последним) элементом массива.

Структура дерева разбиений приведена на рис. 7.3.

Дерево разбиений области исходных данных бинарного поиска

 

Это дерево имеет 11 листьев. Каждый лист задает отдельный тестовый вариант. Покажем тестовые варианты, основанные на проведенных разбиениях.

Тестовый вариант 1 (единичный массив, элемент найден):

ИД: М=15; Кеу=15.

ОЖ.РЕЗ.: Resutt=True; I=1.

Тестовый вариант 2 (четный массив, найден 1-й элемент):

ИД: М=15, 20, 25,30,35,40; Кеу=15.

ОЖ.РЕЗ.: Result=True; I=1.

Тестовый вариант 3 (четный массив, найден последний элемент) :

ИД: М=15, 20, 25, 30, 35, 40; Кеу=40.

ОЖ.РЕЗ:. Result=True; I=6.

Тестовый вариант 4 (четный массив, найден промежуточный элемент):

ИД: М=15,20,25,30,35,40; Кеу=25.

ОЖ.РЕЗ.: Result-True; I=3.

Тестовый вариант 5 (нечетный массив, найден 1-й элемент):

ИД: М=15, 20, 25, 30, 35,40, 45; Кеу=15.

ОЖ.РЕЗ.: Result=True; I=1.

Тестовый вариант 6 (нечетный массив, найден последний элемент):

ИД: М=15, 20, 25, 30,35, 40,45; Кеу=45.

ОЖ.РЕЗ.: Result=True; I=7.

Тестовый вариант 7 (нечетный массив, найден промежуточный элемент):

ИД: М=15, 20, 25, 30,35, 40, 45; Кеу=30.

ОЖ.РЕЗ.: Result=True; I=4.

Тестовый вариант 8 (четный массив, не найден элемент):

ИД: М=15, 20, 25, 30, 35,40; Кеу=23.

ОЖ.РЕЗ.: Result=False; I=?

Тестовый вариант 9 (нечетный массив, не найден элемент);

ИД: М=15, 20, 25, 30, 35, 40, 45; Кеу=24.

ОЖ.РЕЗ:. Result=False; I=?

Тестовый вариант 10 (единичный массив, не найден элемент):

ИД: М=15; Кеу=0.

ОЖ.РЕЗ.: Result=False; I=?

Тестовый вариант 11 (нарушены предусловия):

ИД: М=15, 10, 5, 25, 20, 40, 35; Кеу=35.

ОЖ.РЕЗ.: Аварийное завершение: Массив не упорядочен.

Анализ граничных значений, если он применен правильно, является одним из наиболее полезных методов проектирования тестов. Однако он часто оказывается неэффективным из-за того, что внешне выглядит простым. Граничные условия могут быть едва уловимы и, следовательно, определение их связано с большими трудностями.

Применение функциональных диаграмм

Одним из недостатков анализа граничных значений и эквивалентного разбиения является то, что они не исследуют комбинаций входных условий. Например, пусть программа предыдущего раздела не выполняется, число элементов массива превышает некоторый предел (например, объем памяти). Такая ошибка не обязательно будет обнаружена тестированием граничных значений. Тестирование комбинаций входных условий - непростая задача, поскольку даже при построенном эквивалентном разбиении входных условий число комбинаций обычно астрономически велико. Если нет систематического способа выбора подмножества входных условий, то, как правило, выбирается произвольное подмножество, приводящее к неэффективному тесту.

Метод функциональных диаграмм или диаграмм причинно-следственных связей помогает систематически выбирать высокорезультативные тесты. Он дает полезный побочный эффект, так как позволяет обнаруживать неполноту и неоднозначность исходных спецификаций, Функциональная диаграмма представляет собой формальный язык, на который транслируется спецификация, написанная на естественном языке. Диаграмме можно сопоставить цифровую логическую цепь (комбинаторную логическую сеть), но для ее описания используется более простая нотация (форма записи), чем обычная форма записи, принятая в электронике. Построение тестов этим методом осуществляется в несколько этапов.

1. Спецификация разбивается на "рабочие" участки. Это связано с тем, что функциональные диаграммы становятся слишком громоздкими при применении данного метода к большим спецификациям. Например, когда тестируется система разделения времени, рабочим участком может быть спецификация отдельной команды. При тестировании компилятора в качестве рабочего участка можно рассматривать каждый отдельный оператор языка программирования.

2. В спецификации определяются причины и следствия. Причина есть отдельное входное условие или класс эквивалентности входных условий. Следствие есть выходное условие пли преобразование системы (остаточное действие, которое входное условие оказывает на состояние программы или системы). Например, если сообщение программе приводит к обновлению основного файла, то изменение в нем и является преобразованием системы; подтверждающее сообщение было бы выходным условием. Причины и следствия определяются путем последовательного (слово за словом) чтения спецификации. При этом выделяются слова или фразы, которые описывают причины и следствия. Каждым причине и следствию приписывается отдельный номер.

3. Анализируется семантическое содержание спецификации, которая преобразуется в булевский граф, связывающий причины и следствия. Это и есть функциональная диаграмма.

4. Диаграмма снабжается примечаниями, задающими ограничения и описывающими комбинации причин и (или) следствий, которые являются невозможными из-за синтаксических или внешних ограничений.

5. Путем методического прослеживания состояний условий диаграммы она преобразуется в таблицу решений с ограниченными входами. Каждый столбец таблицы решений соответствует тесту.

6. Столбцы таблицы решений преобразуются в тесты.

Используется автоматный подход к решению задачи.

Шаги способа:

1)для каждого модуля перечисляются причины (условия ввода или классы эквивалентности условий ввода) и следствия (действия или условия вывода). Каждой причине и следствию присваивается свой идентификатор;

2) разрабатывается граф причинно-следственных связей;

3) граф преобразуется в таблицу решений;

4) столбцы таблицы решений преобразуются в тестовые варианты

Базовые символы для записи функциональных диаграмм показаны рисунке

Базовые логические отношения функциональных диаграмм.

Рассмотрим построение ФД и тестового набора для следующей спецификации:

Функция f принимает два параметра. Первый может принимать значение в диапазоне 0¸10 или 20¸100. Второй параметр должен быть типа char. В этом случае возвращается код успешного завершения функции f - O'k. Если первый параметр неправильный, то выдается сообщений ErrMes1. Если второй параметр неправильный, то выдается сообщений ErrMes2.

Причинами будут:

1. Первый параметр лежит в диапазоне 0¸10;

2. Первый параметр лежит в диапазоне 20¸100;

3. Второй параметр типа char.

Следствия:

1. Возвращается код успешного завершения (31);

2. Выдается сообщение ErrMes1(32);

3. Выдается сообщение ErrMes2.(33)

 

 

Косая черта означает отрицание, а объединение пунктирной линией через знак Е - одновременное существование только одной из причин. В диаграмме введен узел 11, для объединения причин 1 и 2 по логическому ИЛИ.

Далее для ФД составляется таблица истинности, в которой число столбцов определяется возможными наборами значений причин.

Таблица решений

Причины \Тесты
...            

Каждый из 6 столбцов является тестовым набором

Отметим, что здесь создан промежуточный узел 11.

Хотя диаграмма отображает спецификацию, она содержит невозможную комбинацию причин - причины 1 и 2 не могут быть установлены в 1 одновременно. В большинстве программ определенные комбинации причин невозможны из-за синтаксических или внешних ограничений (например, символ не может принимать значения "А" и "В" одновременно). В этом случае используются дополнительные логические ограничения.:

Ограничение Е устанавливает, что Е должно быть истинным, если хотя бы одна из причин - а или b - принимает значение 1 (а и b не могут принимать значение 1 одновременно). Ограничение I устанавливает, что по крайней мере, одна из величин а, b или с всегда должна быть равной 1 (а, b и с не могут принимать значение 0 одновременно). Ограничение 0 устанавливает, что одна и только одна из величин а или b должна быть равна 1. Ограничение R устанавливает, что если а принимает значение 1,то b должна принимать значение 1 (т. е. невозможно, чтобы а было равно 1, а b - 0). Часто возникает необходимость в ограничениях для следствий. Ограничение М на рис. 26.6 устанавливает, что если следствие а имеет значение 1, то следствие b должно принять значение 0.

Как видно из рассмотренного выше примера, физически невозможно, чтобы причины 1 и 2 присутствовали одновременно, но возможно, чтобы присутствовала одна из них. Следовательно, они связаны ограничением Е

Проиллюстрируем использование функциональных диаграмм для получения тестов. С этой целью воспользуемся спецификацией на команду отладки в интерактивной системе.

Рассмотрим программу расчета за электричество по среднему или переменному тарифу:

При расчете по среднему тарифу

- при месячном потреблении менее 100кВт/ч, выставляется фиксированная сумма

- при месячном потреблении >= 100кВт/ч, применяется процедура пересчета А.

При расчете по переменному тарифу

- при месячном потреблении менее 100кВт/ч, т/ч, применяется процедура пересчета А.

- при месячном потреблении более или = 100кВт/ч, т/ч, применяется процедура пересчета В.

I. Определим причины:

1. расчет по среднему тарифу

2. расчет по переменному тарифу

3. месячное потребление менее 100кВт/ч

4. месячное потребление более 100кВт/ч

Следствия

101 минимальная стоимость

102 процедура А

103 процедура В

Таблица решений для расчета оплаты за электричество

Номера столбцов — >
Условия Причины
   
   
   
  Вторичные причины
   
Действия Следствия
   
   

Преобразование каждого столбца таблицы в тестовый вариант. В нашем примере таких вариантов четыре.

Тестовый вариант 1 (столбец 1):

ИД: расчет по среднему тарифу; месячное потребление электроэнергии 75 кВт/ч.

ОЖ.РЕЗ.: минимальная месячная стоимость.

Тестовый вариант 2 (столбец 2):

ИД: расчет по переменному тарифу; месячное потребление электроэнергии 90 кВт/ч.

ОЖ.РЕЗ.: процедура A планирования расчета.

Тестовый вариант 3 (столбец 3):

ИД: расчет по среднему тарифу; месячное потребление электроэнергии 100 кВт/ч.

ОЖ.РЕЗ.: процедура А планирования расчета.

Тестовый вариант 4 (столбец 4):

ИД: расчет по переменному тарифу; месячное потребление электроэнергии 100 кВт/ч.

ОЖ.РЕЗ.: процедура В планирования расчета.