Как стать автором
Поиск
Написать публикацию
Обновить

Оценка затрат на разработку через TDD

Время на прочтение4 мин
Количество просмотров4.8K

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


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


Как система, я хочу отправить на проверку KYC сервису персональные данные пользователя


И список задач к ней:


  1. Реализовать получение персональных данных пользователя из локальной базы
  2. Реализовать создание папки в KYC сервисе с указанием в метаданных папки персональных данных пользователя
  3. Реализовать создание запроса на проверку данных папки в KYC сервисе
  4. Реализовать сохранение информации о запросе на проверку персональных данных в локальной базе

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


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


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


describe('upload personal info', () => {

  const HttpFake = require('HttpFake');
  const http = new HttpFake();
  const store = require('../../src/store');
  const handler = require('../../src/kyc/createFolder');
  const rules = require('../../src/importRules');
  const httpOptions = {
    hostname: 'http://kycservice',
    port: 80,
    path: '/api/folder',
    body: {
      meta_data: {
        firstName: 'Jack',
        lastName: 'Sparrow',
        birthDate: '06/01/1740'
      }
    },
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    }
  };
  const httpResponse = {
    statusCode: 200,
    body: {
      folder_id: '0x382974',
      meta_data: {
        firstName: 'Jack',
        lastName: 'Sparrow',
        birthDate: '06/01/1740'
      }
    },
    headers: {
        'Content-Type': 'application/json'
    }
  };

  let context = null,
      handle = null;

  beforeEach(() => {
    context = {
      http,
      store,
      rules
    };

    handle = handler.bind(context, ['folder']);

    const person = {
      firstName: 'Jack',
      lastName: 'Sparrow',
      birthDate: '06/01/1740'
    };
    store.dispatch({ type: 'PERSON', person });
  });

  it('should assign store folder state value', () => {

    http.expect(httpOptions);
    http.returns(httpResponse);

    const assert = checkExportResult.bind(context, [done]);
    store.subscribe(assert);

    handle();
  });

  function checkExportResult(args){

    const folder = store.getState().folder;

    if(folder === null)
      return;

    expect(folder.folder_id).toEqual('0x382974');
    expect(folder.meta_data.firstName).toEqual('Jack');
    expect(folder.meta_data.lastName).toEqual('Sparrow');
    expect(folder.meta_data.birthDate).toEqual('06/01/1740');

    const checkIsCompleted = args[0];
    checkIsCompleted();
  }
});

Модульный тест второй задачи разложился аж в 100 строчек кода, и на его реализацию у меня ушло около часа времени. При этом первые пять строчек на некоторое время погрузили меня в размышления на тему "как бы мне реализовать имитацию отправки http запросов?", пока я не вспомнил что у меня уже есть некая псевдо-http реализация, имитирующая как раз отправку нужных мне POST запросов. Хорошо. Вот у меня есть тест. Стало ли мне понятнее сколько может потребоваться времени на реализацию нужной функциональности?


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


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


  1. Реализовать получение персональных данных пользователя из локальной базы
  2. Реализовать создание папки в KYC сервисе с указанием в метаданных папки персональных данных пользователя —
  3. Реализовать создание запроса на проверку данных папки в KYC сервисе —
  4. Реализовать сохранение информации о запросе на проверку персональных данных в локальной базе —

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

Теги:
Хабы:
Всего голосов 16: ↑14 и ↓2+12
Комментарии1

Публикации

Ближайшие события