>>Из-за этого и не такие продукты теряли популярность и интерес у большого числа юзверев.
Это ваши же слова пару этажами выше. У меня тоже нет желания гуглить им подтверждения. Я привел 3 продукта, в которых OpenSource версия нормально существует рядом с коммерческой версии, вы ничем не подтвердили сови слова.
Да, проприентарный коммерческий Solaris стал бесплатным только в 9 версии и существовал задолго до OpenSolaris. И после появления последнего спокойно вместе с ним существовал до покупки Sun.
Многоуважаемый капитан не приведет ли нам пример крупного OpenSource проекта, который бы потерял юзеров из-за наличия коммерческой версии? IntellJ вполне себе сочетает OpenSource и более функциональную коммерческую версию своей IDEA, RedHat вполне себе успешно продает RHEL при наличии полностью бесплатной Fedora. Всеми любимый Анроид в своей свободной инкарнации идет без сервисов гугла и для их включения на девайсе вендоры должны заключить с гуглом договор.
Как вы определите что p1 и p2 это один объект не смотря в код и не делая явных проверок?
Говнокодить можно на чем угодно. Повторюсь, кеш — это просто не самое удачное приминение для Factory-конструктора
Вызывающий код должен знать только публичный интерфейс библоиотеки. Factory-конструктор или обычный — это детали реализации, которые вам, как пользователю библиотеки знать незачем.
И перечитайте пример кода еще раз. Factory Constructor != конструктор, всегда возвращающий один и тот же объект. Просто в гугле не очень удачный пример выбрали для демонстрации этой фичи
Первый пункт, это же не особенность языка в целом, это особенность конкретного примера Factory конструктора. Если такое поведение не нравится, просто не пишите такие конструкторы
Сейчас попробую представить.
FileCache от ФС нужно следующее:
1. При вызове save создать файл.
2. При вызове load вернуть файл.
3. Для заданного файла вернуть время его создания
Извиняюсь, не пишу на PHP, поэтому приведу пример на Java-подобном псевдокоде.
Всю работу с ФС я бы выделил в отдельный класс:
class FileSystem {
void saveFile(filename, data);
bytes[] loadFile(filename);
Time getFileTime(filename);
}
Экземпляр этого класса добавил бы в виде поля к FileCache. Скорей всего, он бы инициализоровался в конструкторе чтобы все это происходило максимально прозрачно для production-кода. Для тестов бы оставил сеттер, чтобы возможно было заменить объект на стаб или мок.
Тесты бы поменял следующим образом:
testSettingCacheDir — FileSystem заменяется на мок, ожидаем вызова saveFile с требуемым именем файла и данными. Как мне кажется, этого будет достаточно, проверка на количество файлов до и после лишняя.
testSettingCacheLifetime — FileSystem заменется на стаб, в getFileTime возращающий время, когда кеш уже невалиден. Проверяем, что load возращает false. Затем, заменяем стаб на другой, возращающий еще валидное для кеша время и тестовые данные для какого-либо файла и проверяем, что cache->load возвращает валидные данные.
testLoadShouldReturnFalseOnNonexistId — FileSystem заменяем на стаб, возвращющий null для какого-либо файла и проверяем что load возвращает null.
Я могу и ошибатся, буду рад услышать комментарии от более опытных людей.
Очень жаль, что тема нашла такой маленький отклик, тестирование сложных модулей, взаимодействующий с внешними ресурсами, как мне кажется, очень слабо освещенна и вы молодец, что подняли ее.
Я не гуру TDD, тоже новичек в этом деле, но попробую дать пару советов:
1) Проверка на реализацию CacheInterface лишняя. В статически типизированных языках эта ошибка обнаружится на этапе компиляции, в динамических — при попытке вызвать нереализованный метод. Все методы интерфейся CacheInterface вы зовете в дальнейших тестах, поэтому ошибку обнаржуите и без этой проверки
2) В своих тестах стараюсь придерживаться такого правила: каждый тест проверяет не более одного метода. Т.е. ответ на ваш первый вопрос: тест может тестировать кусок метода, челый метод, но не несколько методов сразу.
3) В тестах для кеша работу с ФС я бы тоже заменил на Stub. Юнит-тест не должен зависить от внешних файлов/сервисов.
Для Java и Python как правило есть алтернативы и если что-то не устраивает, всегда можно использовать что-то другое. Для client-side кода в браузере алтернатив нет (имею ввиду чистый бразуер, без flash/silverlight/java/etc). Именно отсюда ноги растут у GWT, CoffeScript, Pyjamas, а теперь и Dart.
Это ваши же слова пару этажами выше. У меня тоже нет желания гуглить им подтверждения. Я привел 3 продукта, в которых OpenSource версия нормально существует рядом с коммерческой версии, вы ничем не подтвердили сови слова.
Да, проприентарный коммерческий Solaris стал бесплатным только в 9 версии и существовал задолго до OpenSolaris. И после появления последнего спокойно вместе с ним существовал до покупки Sun.
>подписки на использование
>использование
И да, пример OpenSource-проекта уровня ngnix от которого отвернулись юзеры после появления коммерческой версии?
Я: «И ленин такой молодой. B юный Октябрь впереди»
Он: «Молодежная премия в этом месяце»
Red Hat Enterprise Linux Server Self-support (up to 1 guest) $349/socket-pair
Если он self-support, то за что платится $350?
Что вы хотели сказать про Eclipse я вообще не понял
Гуру: «Эта рыба моя мечта! Великий IDE!»
Он имел ввиду Eclipse?
global oneEvilObject = {x:1, y:2, z:3};
function Point() {
return oneEvilObject;
}
p1 = new Point();
p2 = new Point();
Как вы определите что p1 и p2 это один объект не смотря в код и не делая явных проверок?
Говнокодить можно на чем угодно. Повторюсь, кеш — это просто не самое удачное приминение для Factory-конструктора
И перечитайте пример кода еще раз. Factory Constructor != конструктор, всегда возвращающий один и тот же объект. Просто в гугле не очень удачный пример выбрали для демонстрации этой фичи
FileCache от ФС нужно следующее:
1. При вызове save создать файл.
2. При вызове load вернуть файл.
3. Для заданного файла вернуть время его создания
Извиняюсь, не пишу на PHP, поэтому приведу пример на Java-подобном псевдокоде.
Всю работу с ФС я бы выделил в отдельный класс:
class FileSystem {
void saveFile(filename, data);
bytes[] loadFile(filename);
Time getFileTime(filename);
}
Экземпляр этого класса добавил бы в виде поля к FileCache. Скорей всего, он бы инициализоровался в конструкторе чтобы все это происходило максимально прозрачно для production-кода. Для тестов бы оставил сеттер, чтобы возможно было заменить объект на стаб или мок.
Тесты бы поменял следующим образом:
testSettingCacheDir — FileSystem заменяется на мок, ожидаем вызова saveFile с требуемым именем файла и данными. Как мне кажется, этого будет достаточно, проверка на количество файлов до и после лишняя.
testSettingCacheLifetime — FileSystem заменется на стаб, в getFileTime возращающий время, когда кеш уже невалиден. Проверяем, что load возращает false. Затем, заменяем стаб на другой, возращающий еще валидное для кеша время и тестовые данные для какого-либо файла и проверяем, что cache->load возвращает валидные данные.
testLoadShouldReturnFalseOnNonexistId — FileSystem заменяем на стаб, возвращющий null для какого-либо файла и проверяем что load возвращает null.
Я могу и ошибатся, буду рад услышать комментарии от более опытных людей.
Очень жаль, что тема нашла такой маленький отклик, тестирование сложных модулей, взаимодействующий с внешними ресурсами, как мне кажется, очень слабо освещенна и вы молодец, что подняли ее.
1) Проверка на реализацию CacheInterface лишняя. В статически типизированных языках эта ошибка обнаружится на этапе компиляции, в динамических — при попытке вызвать нереализованный метод. Все методы интерфейся CacheInterface вы зовете в дальнейших тестах, поэтому ошибку обнаржуите и без этой проверки
2) В своих тестах стараюсь придерживаться такого правила: каждый тест проверяет не более одного метода. Т.е. ответ на ваш первый вопрос: тест может тестировать кусок метода, челый метод, но не несколько методов сразу.
3) В тестах для кеша работу с ФС я бы тоже заменил на Stub. Юнит-тест не должен зависить от внешних файлов/сервисов.