Промо кодове: от заявката до пускането
Накратко: Една заявка, „искам промо кодове за есента“, минава през всичко от курса. Въпросите намират нуждата и хората, които никой не пита. Сторито се разбива по правилата, срокът минава през Example Mapping. Правилата на кода стават сценарии срещу система с грешки, а понеже промяната пипа сумата, и доставката се пази от регресия. Хванатата грешка става доклад, два сценария стават код, а матрицата казва какво се пипа, когато изискването се смени.
Проблем
Заявката
Собственикът на магазина пише в понеделник сутрин:
„Искам промо кодове за есента. 10 % отстъпка, до края на ноември. Пускаме след две седмици.“
Три изречения. В тях има поне пет правила, които никой още не е казал, една отворена тема с пари и един човек, който ще разбере за промяната чак когато не може да си свърши работата. В този проект минаваш целия път: от трите изречения до пуснатата и проверена промяна.
Идеята
Пътят
Всяка стъпка е от модул на курса:
- въпросите: нуждата зад заявката и хората, които трябва да се питат;
- сторито и разбиването: заявката е голяма; реже се по правилата;
- Example Mapping: правилата, примерите и въпросите за срока на кода;
- сценариите и тестовете: правилата на кода стават сценарии; промяната пипа и сумата, а от нея зависи доставката, затова тя се пази от регресия;
- докладът: грешката, която промяната внесе, описана така, че да се поправи от първия път;
- автоматизацията: два сценария за промо кода стават код на четирите езика;
- матрицата и промяната: какво покриват тестовете и какво се пипа, когато изискването се смени.
По-точно, за любопитните
В браузъра сценариите се пускат срещу система с грешки. За промо кода тя знае три от правилата: 10 %, намалените продукти и коя отстъпка важи с лоялността. Срокът и „Кодът вече е ползван“ не са в нея: те са в картата, в матрицата и в автоматизацията, където сценариите се пускат с истинските инструменти. Регресията, таблицата и докладът са за доставката: промяната с кода сменя сумата, от която доставката зависи, и тя трябва да остане вярна.
Пробвай
Въпросите
Идеята
Отговорите
След разговора със собственика, маркетинга и счетоводството заявката изглежда така:
- нуждата: повече нови клиенти през есента. Мярка: първи поръчки от нови клиенти на месец, сравнени с миналата есен; ще се мери в края на ноември;
- правилата: кодът дава 10 %; не важи за намалени продукти; ползва се в една платена поръчка („Кодът вече е ползван“); важи до последния си ден включително („Кодът е изтекъл“); с лоялността не се сумира, важи по-голямата;
- счетоводството: иска да вижда с кой код е дадена всяка отстъпка;
- отворен въпрос: прагът от 50 € за безплатна доставка преди отстъпката ли се смята, или след нея. Решава собственикът; дотогава не се решава от никого друг.
Пет правила в едно стори са много. Следващата стъпка е разбиването.
Упражнение
Сторито и картата
1. Разбиването. Сторито с всички правила на кода е твърде голямо за една итерация.
Избери модела, по който се реже сторито, после сглоби разбиването в реда, в който се прави.
Като клиент искам да въведа промо код и да получа отстъпка, за да купя по-евтино.
Стъпка 2: Кои парчета и в какъв ред?
Добави парчетата, които образуват разбиването, и ги подреди: първото се прави първо.
Парчетата
Разбиването
Модел
- По правилата на бизнеса: Отстъпката е една, но правилата са пет: 10 %, без намалените, една платена поръчка, срок и коя отстъпка важи с лоялността. Всяко правило може да се направи, покаже и провери отделно.
Примерното разбиване
- Кодът дава 10 % на обикновените продукти
- Намалените продукти остават без отстъпката на кода
- Кодът се ползва в една платена поръчка; после „Кодът вече е ползван“
- Кодът важи до последния си ден; после „Кодът е изтекъл“
- Лоялен клиент с код: важи по-голямата отстъпка
Всяко правило е стори, което може да се покаже само. 10 % е основата и е първо. „Важи по-голямата“ има смисъл, когато има две отстъпки, затова е последно. Полето в количката и таблицата в базата са слоеве: никой не може да опита само тях.
2. Срокът на кода. Първото парче след 10 % е срокът. Трите амиго седнаха с картите.
Сложи всяка карта на мястото ѝ, после реши какво е сторито.
Като клиент искам да знам до кога важи кодът, за да го ползвам навреме.
За всяка карта натисни „Сложи като…“ и избери: правило (става колона), пример към правило или въпрос. Стрелките местят между изборите, Esc затваря. Може и с мишката: влачи картата до мястото ѝ.
Правила
Още няма правила. Сложи карта като правило и тя става колона.
Въпроси
- Още няма въпроси.
Неподредени карти
Изтекъл код се отказва със „Кодът е изтекъл“, а сумата остава без отстъпка
Поръчка на 30 ноември с ЕСЕН10: тениска за 20,00 € е 18,00 €
Кодът е въведен на 30 ноември в 23:50, а поръчката е платена на 1 декември в 00:10. Важи ли?
Последният ден свършва в полунощ по чие време: на магазина или на клиента?
Кодът важи до последния си ден включително
Поръчка на 1 декември с ЕСЕН10: „Кодът е изтекъл“, тениската е пак 20,00 €
ЕСЕН10 важи до 30 ноември. Поръчка на 15 ноември: тениска за 20,00 € е 18,00 €
Подредената дъска
- Кодът важи до последния си ден включително
- ЕСЕН10 важи до 30 ноември. Поръчка на 15 ноември: тениска за 20,00 € е 18,00 €
- Поръчка на 30 ноември с ЕСЕН10: тениска за 20,00 € е 18,00 €
- Изтекъл код се отказва със „Кодът е изтекъл“, а сумата остава без отстъпка
- Поръчка на 1 декември с ЕСЕН10: „Кодът е изтекъл“, тениската е пак 20,00 €
Въпроси
- Последният ден свършва в полунощ по чие време: на магазина или на клиента?
- Кодът е въведен на 30 ноември в 23:50, а поръчката е платена на 1 декември в 00:10. Важи ли?
Какво е сторито? Готово за работа. Двата въпроса са за един и същ момент, полунощта на последния ден, и ги решава собственикът с едно изречение. Правилата и примерите са ясни, работата може да започне, а отговорът става още един пример.
Двата въпроса са за полунощта на последния ден. Изглеждат дребни, но от отговора зависи кой клиент ще види „Кодът е изтекъл“ в 00:10. Ще ги срещнеш пак в автоматизацията.
Упражнение
Сценариите за кода
Три от правилата от разбиването се пускат още тук: 10 %, намалените продукти и лоялният клиент с код. По един сценарий за пример, на езика на собственика.
Напиши сценариите за промо кода, така че да се хванат и шестте грешки около отстъпките.
Решение
# language: bg
Функционалност: Промо код
Сценарий: Кодът дава 10 % на продукт без намаление
Дадено валиден промо код
И продукт без намаление
И клиент без лоялност
Когато клиентът плаща
То отстъпката е 10 %
Сценарий: Кодът не важи за продукт в намаление
Дадено валиден промо код
И продукт в намаление
И клиент без лоялност
Когато клиентът плаща
То няма отстъпка
Сценарий: Лоялен клиент с код получава по-голямата отстъпка
Дадено лоялен клиент
И валиден промо код
И продукт без намаление
Когато клиентът плаща
То отстъпката е 10 %
Сценарий: Лоялен клиент с код за намален продукт запазва лоялността
Дадено лоялен клиент
И валиден промо код
И продукт в намаление
Когато клиентът плаща
То отстъпката е 5 %
Сценарий: Лоялен клиент без код
Дадено лоялен клиент
И без промо код
И продукт без намаление
Когато клиентът плаща
То отстъпката е 5 %
Най-коварните грешки са при лоялния клиент: дали отстъпките се събират, коя печели и какво става с лоялността, когато кодът не важи за продукта. А лоялният клиент без код също е пример.
Идеята
Промяната пипа доставката
Промо кодът сменя сумата на количката. От сумата зависи доставката: безплатна от 50,00 € включително, иначе 4,90 €. Програмистът на кода ще пипне точно сметката на сумата.
Каквото и да реши собственикът за прага преди или след отстъпката, правилото за доставката от сумата трябва да остане вярно. Затова преди промяната доставката се пази от регресия: сценарии за договорените примери и тестове за техническите случаи, които падат, ако нещо около границата се счупи.
Упражнение
Регресията на доставката
1. Сценариите. Малко сценарии, по един за всеки договорен пример.
Напиши сценариите за доставката, така че да се хванат петте грешки около границата и празната количка.
Решение
# language: bg
Функционалност: Безплатна доставка
Сценарий: Поръчка точно на границата
Дадено количка за 50,00 €
Когато поръчам
То доставката е безплатна
Сценарий: Поръчка малко под границата
Дадено количка за 49,99 €
Когато поръчам
То доставката е 4,90 €
Сценарий: Празна количка
Дадено празна количка
Когато поръчам
То поръчката е отказана
Трите примера са тези от Example Mapping за доставката: точно 50,00 €, 49,99 € и празна количка. 49,00 € е под границата, но далеч от нея: ако сумата се закръгля до евро, 49,00 € пак е 49, и грешката минава.
2. Техническите случаи. Таблицата е за теста на ниво компонент: случаите, които бизнесът не иска да чете.
Напиши случаите, които хващат всички шест грешки, включително остатъка от старата тарифа при големи поръчки.
Правилото: Доставката е безплатна при поръчка от 50 € включително, иначе е 4,90 €. Празна количка не се поръчва.
| Вход | Очаквано | Правилната система | |||
|---|---|---|---|---|---|
| # | Сума на количката | Отказ | Доставка | ||
Празна клетка за резултат не се проверява. Сумите се пишат като 49,99.
Решение
| Сума на количката | Отказ | Доставка |
|---|---|---|
| 0 | да | |
| 49,99 | не | 4,90 |
| 50 | не | 0 |
| 150 | не | 0 |
Голямата поръчка (150 €) не е в сценариите, защото бизнесът не я е договарял като пример. Но остатъкът от старата тарифа („от 100 € пак 4,90 €“) се вижда само над 100 €.
Упражнение
Хванатата грешка
1. Докладът. Програмистът на промо кода смята сумата с дробни числа и я закръгля до цели евро. Сценарият за 49,99 € пада.
Намери сума, при която грешката се вижда, и напиши доклада.
при суми с центове малко под 50 €
Правилото: Доставката е безплатна при поръчка от 50 € включително, иначе е 4,90 €. Празна количка не се поръчва.
Стъпки за възпроизвеждане
- Още няма стъпки. Добави ги от речника отдолу.
Стъпките са от речника на функционалността, както в сценариите. Стойностите се пишат в самата стъпка: сумата като 50,00.
Примерният доклад
- Заглавие
- Доставката е безплатна за поръчка за 49,50 €
- Стъпки за възпроизвеждане
- Дадено количка за 49,50 €
- Когато поръчам
- Очаквано
- доставката е 4,90 €
- Получено
- доставката е безплатна
- Тежест
- средна. Магазинът губи 4,90 € само на поръчките между 49,50 € и 49,99 €. Обхватът е тесен, но грешката е истинска, а клиентите, които я открият, ще я ползват.
- Приоритет
- висок. Грешката влезе с промяната за промо кода, която тръгва с кампанията. Поправката е малка и трябва да е в същото пускане, иначе кампанията ще я разнесе.
Грешката се вижда между 49,50 € и 49,99 €: там закръглянето прави 50 €. При 49,00 € и двете системи взимат 4,90 €, затова такъв доклад не възпроизвежда нищо. Приоритетът е висок, защото грешката тръгва с кампанията.
Идеята
Автоматизацията на два сценария
Двата сценария за промо кода, които собственикът прочете и прие:
# language: bgФункционалност: Промо код Промо кодът дава 10 % отстъпка до последния си ден включително.
Сценарий: Кодът дава 10 % Дадено количка за 20,00 € Когато приложа кода ЕСЕН10 То сумата е 18,00 €
Сценарий: Изтекъл код Дадено количка за 20,00 € И кодът ЕСЕН10 е изтекъл Когато приложа кода ЕСЕН10 То виждам, че кодът е изтекъл И сумата е 20,00 €Класът, който прилага кода. Сумата е в центове, а денят е вход, не „днес“: това е отговорът на въпроса за полунощта от картата и на урока за тестовете в CI:
package shop;
import java.time.LocalDate;
public class PromoCode { private final String code; private final LocalDate lastDay;
public PromoCode(String code, LocalDate lastDay) { this.code = code; this.lastDay = lastDay; }
// 10 % от сумата в центове. Изтекъл код се отказва. public int apply(int total, LocalDate day) { if (day.isAfter(lastDay)) { throw new IllegalArgumentException("Кодът е изтекъл"); } return total - total / 10; }}namespace Shop;
public class PromoCode(string code, DateOnly lastDay){ public string Code => code;
// 10 % от сумата в центове. Изтекъл код се отказва. public int Apply(int total, DateOnly day) { if (day > lastDay) { throw new ArgumentException("Кодът е изтекъл"); } return total - total / 10; }}class PromoCode: def __init__(self, code, last_day): self.code = code self.last_day = last_day
def apply(self, total, day): """10 % от сумата в центове. Изтекъл код се отказва.""" if day > self.last_day: raise ValueError("Кодът е изтекъл") return total - total // 10export class PromoCode { constructor(code, lastDay) { this.code = code; this.lastDay = lastDay; }
// 10 % от сумата в центове. Изтекъл код се отказва. apply(total, day) { if (day > this.lastDay) { throw new Error("Кодът е изтекъл"); } return total - Math.floor(total / 10); }}Стъпката „Когато“ прилага кода, а „То“ проверява съобщението:
@When("приложа кода {word}")public void apply(String code) { try { total = new PromoCode(code, LAST_DAY).apply(total, today); } catch (IllegalArgumentException e) { refusal = e.getMessage(); }}[When("приложа кода {word}")]public void Apply(string code){ try { total = new PromoCode(code, LastDay).Apply(total, today); } catch (ArgumentException e) { refusal = e.Message; }}@when("приложа кода {code}")def step_apply(context, code): try: context.total = PromoCode(code, LAST_DAY).apply(context.total, context.today) except ValueError as e: context.refusal = str(e)When("приложа кода {word}", function (code) { try { this.total = new PromoCode(code, LAST_DAY).apply(this.total, this.today); } catch (e) { this.refusal = e.message; }});@Then("виждам, че кодът е изтекъл")public void toldExpired() { assertEquals("Кодът е изтекъл", refusal);}[Then("виждам, че кодът е изтекъл")]public void ToldExpired() => Assert.Equal("Кодът е изтекъл", refusal);@then("виждам, че кодът е изтекъл")def step_told_expired(context): assert context.refusal == "Кодът е изтекъл", f"съобщение: {context.refusal}"Then("виждам, че кодът е изтекъл", function () { assert.equal(this.refusal, "Кодът е изтекъл");});Целият файл със стъпките, пуснат с истинския инструмент. Двата сценария минават:
package shop;
import io.cucumber.java.ParameterType;import io.cucumber.java.en.Given;import io.cucumber.java.en.Then;import io.cucumber.java.en.When;
import java.time.LocalDate;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class PromoSteps { // Последният ден на кода в сценариите. private static final LocalDate LAST_DAY = LocalDate.of(2026, 11, 30);
private int total; private LocalDate today = LocalDate.of(2026, 11, 15); private String refusal;
@ParameterType(name = "сума", value = "\\d+,\\d{2}") public int amount(String text) { return Integer.parseInt(text.replace(",", "")); }
@Given("количка за {сума} €") public void cart(int cents) { total = cents; }
@Given("кодът {word} е изтекъл") public void expired(String code) { today = LAST_DAY.plusDays(1); }
@When("приложа кода {word}") public void apply(String code) { try { total = new PromoCode(code, LAST_DAY).apply(total, today); } catch (IllegalArgumentException e) { refusal = e.getMessage(); } }
@Then("сумата е {сума} €") public void totalIs(int cents) { assertEquals(cents, total); }
@Then("виждам, че кодът е изтекъл") public void toldExpired() { assertEquals("Кодът е изтекъл", refusal); }}ОК Изтекъл кодОК Кодът дава 10 %Сценарии: 2, минали: 2, паднали: 0using Reqnroll;using Xunit;
namespace Shop;
[Binding]public class PromoSteps{ // Последният ден на кода в сценариите. private static readonly DateOnly LastDay = new(2026, 11, 30);
private int total; private DateOnly today = new(2026, 11, 15); private string refusal;
[StepArgumentTransformation(@"(\d+,\d{2})", Name = "сума")] public int Amount(string text) => int.Parse(text.Replace(",", ""));
[Given("количка за {сума} €")] public void Cart(int cents) => total = cents;
[Given("кодът {word} е изтекъл")] public void Expired(string code) => today = LastDay.AddDays(1);
[When("приложа кода {word}")] public void Apply(string code) { try { total = new PromoCode(code, LastDay).Apply(total, today); } catch (ArgumentException e) { refusal = e.Message; } }
[Then("сумата е {сума} €")] public void TotalIs(int cents) => Assert.Equal(cents, total);
[Then("виждам, че кодът е изтекъл")] public void ToldExpired() => Assert.Equal("Кодът е изтекъл", refusal);}ОК Изтекъл кодОК Кодът дава 10 %Сценарии: 2, минали: 2, паднали: 0from datetime import date, timedelta
from behave import given, register_type, then, when
from promo_code import PromoCode
# Последният ден на кода в сценариите.LAST_DAY = date(2026, 11, 30)
def parse_amount(text): return int(text.replace(",", ""))
parse_amount.pattern = r"\d+,\d{2}"register_type(Amount=parse_amount)
@given("количка за {total:Amount} €")def step_cart(context, total): context.total = total
@given("кодът {code} е изтекъл")def step_expired(context, code): context.today = LAST_DAY + timedelta(days=1)
@when("приложа кода {code}")def step_apply(context, code): try: context.total = PromoCode(code, LAST_DAY).apply(context.total, context.today) except ValueError as e: context.refusal = str(e)
@then("сумата е {total:Amount} €")def step_total(context, total): assert context.total == total, f"сумата е {context.total}, очаквано {total}"
@then("виждам, че кодът е изтекъл")def step_told_expired(context): assert context.refusal == "Кодът е изтекъл", f"съобщение: {context.refusal}"ОК Изтекъл кодОК Кодът дава 10 %Сценарии: 2, минали: 2, паднали: 0import { Given, When, Then, defineParameterType } from "@cucumber/cucumber";import assert from "node:assert/strict";import { PromoCode } from "../../promo-code.js";
// Последният ден на кода в сценариите.const LAST_DAY = "2026-11-30";
defineParameterType({ name: "сума", regexp: /\d+,\d{2}/, transformer: (text) => Number(text.replace(",", "")),});
Given("количка за {сума} €", function (cents) { this.total = cents;});
Given("кодът {word} е изтекъл", function (code) { this.today = "2026-12-01";});
When("приложа кода {word}", function (code) { try { this.total = new PromoCode(code, LAST_DAY).apply(this.total, this.today); } catch (e) { this.refusal = e.message; }});
Then("сумата е {сума} €", function (cents) { assert.equal(this.total, cents);});
Then("виждам, че кодът е изтекъл", function () { assert.equal(this.refusal, "Кодът е изтекъл");});ОК Изтекъл кодОК Кодът дава 10 %Сценарии: 2, минали: 2, паднали: 0А ако програмистът забрави срока, изтеклият код пак дава 10 %, и сценарият „Изтекъл код“ пада:
package shop;
import java.time.LocalDate;
public class PromoCode { private final String code; private final LocalDate lastDay;
public PromoCode(String code, LocalDate lastDay) { this.code = code; this.lastDay = lastDay; }
// 10 % от сумата в центове. Изтекъл код се отказва. public int apply(int total, LocalDate day) { return total - total / 10; }}ОК Кодът дава 10 %ПАДА Изтекъл код: expected: <Кодът е изтекъл> but was: <null>Сценарии: 2, минали: 1, паднали: 1namespace Shop;
public class PromoCode(string code, DateOnly lastDay){ public string Code => code;
// 10 % от сумата в центове. Изтекъл код се отказва. public int Apply(int total, DateOnly day) { return total - total / 10; }}ОК Кодът дава 10 %ПАДА Изтекъл код: Assert.Equal() Failure: Strings differ Expected: "Кодът е изтекъл" Actual: nullСценарии: 2, минали: 1, паднали: 1class PromoCode: def __init__(self, code, last_day): self.code = code self.last_day = last_day
def apply(self, total, day): """10 % от сумата в центове. Изтекъл код се отказва.""" return total - total // 10ОК Кодът дава 10 %ПАДА Изтекъл код: ASSERT FAILED: съобщение: NoneСценарии: 2, минали: 1, паднали: 1export class PromoCode { constructor(code, lastDay) { this.code = code; this.lastDay = lastDay; }
// 10 % от сумата в центове. Изтекъл код се отказва. apply(total, day) { return total - Math.floor(total / 10); }}ОК Кодът дава 10 %ПАДА Изтекъл код: null !== 'Кодът е изтекъл'Сценарии: 2, минали: 1, паднали: 1По-точно, за любопитните
Сценариите тук не са в речника на двигателя на курса, затова не се проверяват срещу система с грешка в браузъра. Те се пускат с Cucumber-JVM, Reqnroll, behave и cucumber-js, както в модула „Автоматизация“, и изходът им е проверен. Отстъпката се закръгля надолу до цял цент (total / 10 в цели числа); за суми като 20,00 € това няма значение, но е решение, което счетоводството трябва да потвърди.
Упражнение
Матрицата и промяната
1. Покритието и въздействието. Есента мина. Мерката показа, че повечето кодове са ползвани от стари клиенти, и собственикът сменя правилото: кодът важи само за първата поръчка на клиента.
Отбележи връзките. После, във втората стъпка, избери кои тестове трябва да се прегледат при промяната.
Тестове
- Т-1: Нов клиент, тениска за 20,00 € с ЕСЕН10: 18,00 €.
- Т-2: Нов клиент, дънки в намаление за 40,00 € с ЕСЕН10: 40,00 €.
- Т-3: Нов клиент, тениска за 20,00 € и дънки в намаление за 40,00 € с ЕСЕН10: 58,00 €.
- Т-4: Клиентът вече е платил поръчка с ЕСЕН10. В нова поръчка въвежда ЕСЕН10: „Кодът вече е ползван“.
- Т-5: Нов клиент въвежда ЕСЕН10 на 1 декември, след последния ден: „Кодът е изтекъл“.
- Т-6: Лоялен клиент с ЕСЕН10, тениска за 20,00 €: 18,00 €, не 17,00 €.
- Т-7: Нов клиент въвежда ЕСЕН10 на 30 ноември, последния ден: тениска за 20,00 € е 18,00 €.
Натисни клетката, където тестът проверява изискването; отново, за да махнеш връзката. Стрелките местят между клетките, Space или Enter отбелязва.
| Изисквания | Т-1: Нов клиент, тениска за 20,00 € с ЕСЕН10: 18,00 €. | Т-2: Нов клиент, дънки в намаление за 40,00 € с ЕСЕН10: 40,00 €. | Т-3: Нов клиент, тениска за 20,00 € и дънки в намаление за 40,00 € с ЕСЕН10: 58,00 €. | Т-4: Клиентът вече е платил поръчка с ЕСЕН10. В нова поръчка въвежда ЕСЕН10: „Кодът вече е ползван“. | Т-5: Нов клиент въвежда ЕСЕН10 на 1 декември, след последния ден: „Кодът е изтекъл“. | Т-6: Лоялен клиент с ЕСЕН10, тениска за 20,00 €: 18,00 €, не 17,00 €. | Т-7: Нов клиент въвежда ЕСЕН10 на 30 ноември, последния ден: тениска за 20,00 € е 18,00 €. | Покрито от |
|---|---|---|---|---|---|---|---|---|
| И-1 Промо кодът дава 10 % отстъпка. | 0 | |||||||
| И-2 Промо кодът не важи за намалени продукти. | 0 | |||||||
| И-3 Кодът се ползва в една платена поръчка. Втори опит: „Кодът вече е ползван“. | 0 | |||||||
| И-4 Кодът важи до последния си ден включително. След него: „Кодът е изтекъл“. | 0 | |||||||
| И-5 Отстъпките не се сумират: важи по-голямата. | 0 | |||||||
| И-6 В поръчката се вижда с кой код е дадена отстъпката. | 0 | |||||||
| Проверява | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Еталонната матрица
- И-1: Т-1, Т-3
- И-2: Т-2, Т-3
- И-3: Т-4
- И-4: Т-5, Т-7
- И-5: Т-6
- И-6: непокрито
Кои тестове трябва да се прегледат? Т-4, Т-6. „Т-4“ се преглежда: клиентът вече има поръчка, кодът пак се отказва, но с кое съобщение, трябва да се реши. „Т-6“ не е свързан с „И-3“, но лоялният клиент има минали поръчки: кодът вече не важи за него, и тениската става 19,00 € по лоялността. „Т-1“, „Т-2“, „Т-3“, „Т-5“ и „Т-7“ са с нов клиент и остават. Трябва и нов тест: клиент с минала поръчка без код въвежда ЕСЕН10, и кодът се отказва.
„И-6“ дойде от приемното тестване (счетоводството) и още няма тест. При промяната „Т-4“ е свързан с изискването, но „Т-6“ не е: лоялният клиент обаче има минали поръчки, и за него кодът вече не важи. Връзките в матрицата са началото на анализа, не краят.
Тест
Провери се
Свързани уроци
Раздел „Свързани уроци“- Нужно отпреди: Тестове на ниво компонент · Тестовете в CI · Приемното тестване с бизнеса · Мерене след пускането
- Задачи по темата: Проект: промо кодове