Процесс разработки - Листинг 16.10 |
Страница 30 из 37
Листинг 16.10. TecтЛакомки.java
public void тестОтчетаОдногоПосещения() { Лакоика g = new Лакоика(); g.добавитьПосещениеКафе(булочки. стоимость, вес); Отчет r = g.создатьОтчет(); assertEquals(0. r.получитьИзменениеВеса(), дельта); assertEqualз(булочки, г.получитьПотреблениеБулочек(), дельта); assertEquals(0, r.получитьВесНаБулочку(), дельта); assertEquals(стоимость. r.получитьСтоимостьБулочек(), дельта); } При создании этого тестового варианта мы обдумали детали генерации отчета. Во-первых, Лакомка должна обладать методом создатьОтчет. Во-вторых, этот метод должен возвращать объект класса с именем Отчет. В-третьих, Отчет должен иметь несколько методов-селекторов. Значения, возвращаемые методами-селекторами, следует проанализировать. Для вычисления изменения веса (или приращения веса на одну булочку) одного посещения кафе недостаточно. Чтобы вычислить эти значения, необходимы, как минимум, два посещения, С другой стороны, одного визита достаточно, чтобы сосчитать потребление и стоимость булочек. Разумеется, тестовый вариант не компилируется. Поэтому необходимо добавить соответствующие методы и классы. Сначала добавим код, обеспечивающий компиляцию, но не обеспечивающий выполнение тестов.
Листинг 16.11. Лакомка.java, TecтЛакомки.java и Отчет.jаvа Лакомка.java public Отчет создатьОтчет() { return new Отчет(); } ТестЛакомки.java public void тестОтчетаОдногоПосещения() { Лакомка g = new Лакомка(); g.добавитьПосещениеКафе(булочки, стоимость, вес); Отчет r = g.создатьОтчет(); assertEquals(0, r.получитьИзменениеВеса(), дельта); assertEquals(булочки. r.получитьПотреблениеБулочек(), дельта); assertEquals(0. r.получитьВесНаБулочку(), дельта); assertEquals(cтоимость,. r.получитьСтоимостьБулочек(),. дельта); } Отчет.java public class Отчет { public double получитьИзменениеВеса() {return егоИзменениеВеса;} public double получитьВесНаБулочку() {return егоВесНаБулочку;} public double получитьСтоииостьБулочек() {return егоСтоимостьБулочек;} public double получитьЛотреблениеБулочек() {return егоПотреблениеБулочек;} private double егоИзменениеВеса; private double егоВесНаБулочку; private double егоСтоимостьБулочек; private double егоПотреблениеБулочек; } Код в листинге 16.11 компилируется и запускается, но его недостаточно для того, чтобы прошли тесты. Нужен рефакторинг кода. Для начала сделаем минимально возможные изменения.
Листинг 16.12. Лакомка.java и Отчет.java Лакомка.java public Отчет создатьОтчет() { Отчет r = new Отчет(); ПосещениеКафе v = (ПосещениеКафе) егоПосещения. Get(0); // занести в v первый элемент из контейнера посещений r.устВесНаБулочку(0); r.устИзменениеВеса(0); r.устСтоимостьБулочек(v.получитьСтоимость()); r.устПотреблениеБулочек(v.получитьБулочки()): return r; } Отчет.java public void устВесНаБулочку (double wpb) {егоВесНаБулочку = wpb;} public void устИзменениеВес(double kg) {егоИзменениеВеса = kg;} public void устСтоимостьБулочек(double ct) (егоСтоимостьБулочек = ct;} public void устПотреблениеБулочек (double b) {егоПотреблениеБулочек = b;} Предполагаем, что Лакомке разрешено только одно посещение. В этой версии метода создатьОтчет устанавливаются и возвращаются значения свойств Отчета. Такой способ разработки метода создатьОтчет может показаться странным, ведь его реализация не завершена. Однако преимущество по-прежнему в том, что между каждой компиляцией и тестированием вносятся только контролируемые добавления. Если что-то отказывает, можно просто вернуться к предыдущей версии и начать сначала, необходимость в сложной отладке отсутствует. Для завершения кода продумаем тесты для Лакомки без посещений и с несколькими посещениями кафе. Начнем с теста и кода для варианта без посещений.
Листинг 16.13. TecтЛакомки.java и Лакомка.jауа ТестЛакомки.java public void тестОтчетаБезПосещений() { Лакомка g = new Лакомка(); Отчет r= g.создатьОтчет(); assertEquals(0, r.получитьИзменениеВеса(). дельта); assertEquals(0, r.получитьПотреблениеБулочек(), дельта); assertEquals(0, r.получитьВесНаБулочку()), дельта; assertEquals(0, r.получитьСтоимостьБулочек(), дельта); } Лакомка.Java public Отчет создатьОтчет() { Отчет r = new Отчет(); if (егоПосещения.size() = 0) { r.устВесНаБулочку(0); r.устИзиенениеВеса(0); r.устСтоимостьБулочек(0); r.устПотреблениеБулочек(0); } else { ПосещениеКафе v = (ПосещениеКафе) егоПосещения.get(0); // занести в v первый элемент из контейнера посещений r.устВесНаБулочку(0); r.устИзменениеВеса(0); r.устСтоимостьБулочек(v.получитьСтоимость()); r. устПотреблениеБулочек (v.получитьБулочки ()): } return r; } Теперь начнем создавать тестовый вариант для нескольких посещений.
Листинг 16.14. ТестЛакомки.jауа public void тестОтчетаНесколькихПосещений() { Лакомка g = new Лакомка(); g.добавить(ПосещениеКафе(7. 87.5, 60.7); g.добавитьПосещениеКафе(14. 175, 62.1); g.добавитьПосещениеКафе(28, 350. 64.9); Отчет r= g.создатьОтчет(); assertEquals(4.2, r.получитьИзменениеВеса(), дельта); assertEquals(49. r.получитьПотреблениеБулочек(), дельта); assertEquals(0.086, r.получитьВесНаБулочку(), дельта); assertEquals(612.5, r.получитьСтоииостьБулочек(), дельта); } Мы установили число посещений для Лакомки равным трем. Предполагается, что цена булочки составляет 12,5 руб., а изменение веса — 0,1 кг на одну булочку. Таким образом, за 175 руб. лакомка покупает и съедает 14 булочек, полнея на 1,4 кг. Но здесь какая-то ошибка. Скорость изменения веса должна определяться коэффициентом 0,1 кг на одну булочку. А если разделить 4,2 (изменение веса) на 49 (количество булочек), то получаем коэффициент 0,086. В чем причина несоответствия? После размышлений становится понятно, что вес лакомки регистрируется на выходе из кафе. Поэтому приращение веса и потребление булочек во время первого посещения не учитывается. Изменим исходные данные теста.
|