Към съдържанието
wannacode

Промо кодове: от заявката до пускането

Накратко: Една заявка, „искам промо кодове за есента“, минава през всичко от курса. Въпросите намират нуждата и хората, които никой не пита. Сторито се разбива по правилата, срокът минава през Example Mapping. Правилата на кода стават сценарии срещу система с грешки, а понеже промяната пипа сумата, и доставката се пази от регресия. Хванатата грешка става доклад, два сценария стават код, а матрицата казва какво се пипа, когато изискването се смени.

Проблем

Заявката

Собственикът на магазина пише в понеделник сутрин:

„Искам промо кодове за есента. 10 % отстъпка, до края на ноември. Пускаме след две седмици.“

Три изречения. В тях има поне пет правила, които никой още не е казал, една отворена тема с пари и един човек, който ще разбере за промяната чак когато не може да си свърши работата. В този проект минаваш целия път: от трите изречения до пуснатата и проверена промяна.

Идеята

Пътят

Всяка стъпка е от модул на курса:

  1. въпросите: нуждата зад заявката и хората, които трябва да се питат;
  2. сторито и разбиването: заявката е голяма; реже се по правилата;
  3. Example Mapping: правилата, примерите и въпросите за срока на кода;
  4. сценариите и тестовете: правилата на кода стават сценарии; промяната пипа и сумата, а от нея зависи доставката, затова тя се пази от регресия;
  5. докладът: грешката, която промяната внесе, описана така, че да се поправи от първия път;
  6. автоматизацията: два сценария за промо кода стават код на четирите езика;
  7. матрицата и промяната: какво покриват тестовете и какво се пипа, когато изискването се смени.
По-точно, за любопитните

В браузъра сценариите се пускат срещу система с грешки. За промо кода тя знае три от правилата: 10 %, намалените продукти и коя отстъпка важи с лоялността. Срокът и „Кодът вече е ползван“ не са в нея: те са в картата, в матрицата и в автоматизацията, където сценариите се пускат с истинските инструменти. Регресията, таблицата и докладът са за доставката: промяната с кода сменя сумата, от която доставката зависи, и тя трябва да остане вярна.

Пробвай

Въпросите

1. Какъв е първият въпрос към собственика?
2. Кого още трябва да питаш, освен собственика?
3. Прагът за безплатна доставка преди отстъпката ли се смята, или след нея? Собственикът казва: „Не съм мислил.“
4. Кой въпрос е подвеждащ?

Идеята

Отговорите

След разговора със собственика, маркетинга и счетоводството заявката изглежда така:

  • нуждата: повече нови клиенти през есента. Мярка: първи поръчки от нови клиенти на месец, сравнени с миналата есен; ще се мери в края на ноември;
  • правилата: кодът дава 10 %; не важи за намалени продукти; ползва се в една платена поръчка („Кодът вече е ползван“); важи до последния си ден включително („Кодът е изтекъл“); с лоялността не се сумира, важи по-голямата;
  • счетоводството: иска да вижда с кой код е дадена всяка отстъпка;
  • отворен въпрос: прагът от 50 € за безплатна доставка преди отстъпката ли се смята, или след нея. Решава собственикът; дотогава не се решава от никого друг.

Пет правила в едно стори са много. Следващата стъпка е разбиването.

Упражнение

Сторито и картата

1. Разбиването. Сторито с всички правила на кода е твърде голямо за една итерация.

Избери модела, по който се реже сторито, после сглоби разбиването в реда, в който се прави.

Стори

Като клиент искам да въведа промо код и да получа отстъпка, за да купя по-евтино.

Стъпка 1: По какъв модел се разбива?

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 %, намалените продукти и лоялният клиент с код. По един сценарий за пример, на езика на собственика.

Напиши сценариите за промо кода, така че да се хванат и шестте грешки около отстъпките.

GherkinОтстъпки

Идеята

Промяната пипа доставката

Промо кодът сменя сумата на количката. От сумата зависи доставката: безплатна от 50,00 € включително, иначе 4,90 €. Програмистът на кода ще пипне точно сметката на сумата.

Каквото и да реши собственикът за прага преди или след отстъпката, правилото за доставката от сумата трябва да остане вярно. Затова преди промяната доставката се пази от регресия: сценарии за договорените примери и тестове за техническите случаи, които падат, ако нещо около границата се счупи.

Упражнение

Регресията на доставката

1. Сценариите. Малко сценарии, по един за всеки договорен пример.

Напиши сценариите за доставката, така че да се хванат петте грешки около границата и празната количка.

GherkinБезплатна доставка

2. Техническите случаи. Таблицата е за теста на ниво компонент: случаите, които бизнесът не иска да чете.

Напиши случаите, които хващат всички шест грешки, включително остатъка от старата тарифа при големи поръчки.

Правилото: Доставката е безплатна при поръчка от 50 € включително, иначе е 4,90 €. Празна количка не се поръчва.

ВходОчакваноПравилната система
#Сума на количкатаОтказДоставка

Празна клетка за резултат не се проверява. Сумите се пишат като 49,99.

Упражнение

Хванатата грешка

1. Докладът. Програмистът на промо кода смята сумата с дробни числа и я закръгля до цели евро. Сценарият за 49,99 € пада.

Намери сума, при която грешката се вижда, и напиши доклада.

Хванатата грешка: Безплатна доставка

при суми с центове малко под 50 €

Правилото: Доставката е безплатна при поръчка от 50 € включително, иначе е 4,90 €. Празна количка не се поръчва.

Стъпки за възпроизвеждане

  1. Още няма стъпки. Добави ги от речника отдолу.

Стъпките са от речника на функционалността, както в сценариите. Стойностите се пишат в самата стъпка: сумата като 50,00.

Очаквано (какво трябва да стане според правилото)
Получено (какво става в системата с грешката)
Тежест (колко вреди дефектът)
Приоритет (колко бързо да се оправи)

Идеята

Автоматизацията на два сценария

Двата сценария за промо кода, които собственикът прочете и прие:

promo.feature
# language: bg
Функционалност: Промо код
Промо кодът дава 10 % отстъпка до последния си ден включително.
Сценарий: Кодът дава 10 %
Дадено количка за 20,00 €
Когато приложа кода ЕСЕН10
То сумата е 18,00 €
Сценарий: Изтекъл код
Дадено количка за 20,00 €
И кодът ЕСЕН10 е изтекъл
Когато приложа кода ЕСЕН10
То виждам, че кодът е изтекъл
И сумата е 20,00 €

Класът, който прилага кода. Сумата е в центове, а денят е вход, не „днес“: това е отговорът на въпроса за полунощта от картата и на урока за тестовете в CI:

src/main/java/shop/PromoCode.java
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;
}
}

Стъпката „Когато“ прилага кода, а „То“ проверява съобщението:

src/test/java/shop/PromoSteps.java
@When("приложа кода {word}")
public void apply(String code) {
try {
total = new PromoCode(code, LAST_DAY).apply(total, today);
} catch (IllegalArgumentException e) {
refusal = e.getMessage();
}
}
src/test/java/shop/PromoSteps.java
@Then("виждам, че кодът е изтекъл")
public void toldExpired() {
assertEquals("Кодът е изтекъл", refusal);
}

Целият файл със стъпките, пуснат с истинския инструмент. Двата сценария минават:

src/test/java/shop/PromoSteps.java
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, паднали: 0

А ако програмистът забрави срока, изтеклият код пак дава 10 %, и сценарият „Изтекъл код“ пада:

src/main/java/shop/PromoCode.java
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, паднали: 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
Проверява0000000

Тест

Провери се

1. Заявката е за промо кода. Защо в проекта има сценарии и тестове и за доставката?
2. Кое прави матрицата в този проект полезна при промяната на изискването?
3. Кое от тези е „готово“ за промо кодовете?
4. Въпросът „по чие време свършва последният ден“ от картата се оказа важен и в кода. Къде?

Създаден от Иво Гергов като част от кампанията на Evo Tech за достъпно обучение по програмиране ·