Я считаю, что проблема в startAfter(null)
. Когда вы сортируете в порядке возрастания, сначала идут нулевые документы, а затем ненулевые документы. Точный порядок см. В документации Firebase о порядке типов значений .
Когда вы сортируете в порядке убывания, все нулевые документы идут последними, поэтому после нулевых документов ничего не остается для запроса, который нужно вернуть.
Я предлагаю удалить startAfter(null)
, пока у вас не будет значения для него.
Моя практика состоит в том, чтобы тестировать внутренние компоненты через общедоступный API / UI. Если какой-то внутренний код недоступен извне, я выполняю рефакторинг для его удаления.
Я тестирую детали частной реализации, а также общедоступные интерфейсы. Если я изменяю деталь реализации и в новой версии есть ошибка, это позволяет мне лучше понять, где на самом деле ошибка, а не только то, что она вызывает.
Некоторые компиляторы могут сделать определение оптимального размера для вас. Если я правильно помню, компилятор TI28xx автоматически преобразует передачу по значению в передачу по ссылке, если структура превышает определенный размер.
каждому из них может потребоваться «имитировать» компонент другого, чтобы у них было что-то (макет), на котором можно протестировать свой собственный компонент, прежде чем их компонент будет сочтен готовым для последующего «интеграционного тестирования», и до того, как другая команда предоставит свой компонент противЕсли вы разрабатываете всю систему, вы можете расширить всю систему ... например, разработать новое поле графического интерфейса пользователя, новое поле базы данных, новую бизнес-транзакцию и одну новую системный / функциональный тест, все как часть одной итерации, без необходимости разрабатывать «макеты» какого-либо уровня (так как вместо этого вы можете протестировать реальный объект).
Я лично тестирую и защищенные части, потому что они "общедоступны" для унаследованных типов ...
Я согласен с тем, что покрытие кода в идеале должно быть 100%. Это не обязательно означает, что 60 строк кода будут иметь 60 строк тестового кода, но проверяется каждый путь выполнения. Единственное, что раздражает больше, чем ошибка, - это еще не запущенная ошибка.
Тестируя только публичный API, вы рискуете не протестировать все экземпляры внутренних классов. Я действительно констатирую очевидное, говоря это, но я думаю, что это следует упомянуть. Чем больше проверяется каждое поведение, тем легче распознать не только то, что оно нарушено, но и то, что нарушено.
Если вы практикуете чистую разработку, основанную на тестах, вы реализуете любой код только после того, как у вас есть какой-либо неудачный тест, и только когда у вас нет неудачных тестов. Кроме того, реализуйте только самую простую вещь, чтобы пройти тест, который не прошел или не прошел.
В ограниченной практике TDD, которую я имел, я ' Мы видели, как это помогает мне избавиться от модульных тестов для каждого логического условия, создаваемого кодом. Я не совсем уверен, что 100% логических функций моего частного кода доступны через мои общедоступные интерфейсы. Практика TDD кажется дополнением к этой метрике, но все же есть скрытые функции, не разрешенные общедоступными API.
Я полагаю, вы могли бы сказать, что эта практика защищает меня от будущих дефектов в моих общедоступных интерфейсах. Либо вы сочтете это полезным (и позволит вам быстрее добавлять новые функции), либо вы обнаружите, что это пустая трата времени.
Я полагаю, вы могли бы сказать, что эта практика защищает меня от будущих дефектов в моих общедоступных интерфейсах. Либо вы сочтете это полезным (и позволит вам быстрее добавлять новые функции), либо вы обнаружите, что это пустая трата времени.
Я полагаю, вы могли бы сказать, что эта практика защищает меня от будущих дефектов в моих общедоступных интерфейсах. Либо вы сочтете это полезным (и позволит вам быстрее добавлять новые функции), либо вы обнаружите, что это пустая трата времени.
На этот вопрос было получено много отличных ответов, но я хочу добавить несколько собственных замечаний. В качестве предисловия: я консультант крупной компании, которая предоставляет технологические решения широкому кругу крупных клиентов. Я говорю это потому, что, по моему опыту, от нас требуется гораздо более тщательное тестирование, чем от большинства магазинов программного обеспечения (за исключением, возможно, разработчиков API). Вот некоторые шаги, которые мы выполняем для обеспечения качества:
Конечно, я знаю, что не все следуют этому процессу, но если вы посмотрите на него от начала до конца В конце вы можете начать видеть преимущества отдельных компонентов. Я не включил такие вещи, как тесты проверки сборки, так как они происходят в другой график (например, ежедневно). Я лично считаю, что модульные тесты критичны, потому что они дают вам глубокое понимание того, какой конкретный компонент вашего приложения дает сбой в каком конкретном варианте использования. Модульные тесты также помогут вам определить, какие методы работают правильно, чтобы вы не тратили время на изучение их для получения дополнительной информации о сбое, когда с ними все в порядке.
Конечно, модульные тесты также могут ошибаться, но если вы разрабатываете свои тестовые примеры на основе своей функциональной / технической спецификации (она у вас есть, верно?;)), у вас не должно возникнуть особых проблем.
но если вы разрабатываете свои тестовые примеры на основе своей функциональной / технической спецификации (она у вас есть, верно?;)), у вас не должно возникнуть особых проблем. но если вы разрабатываете свои тестовые примеры на основе своей функциональной / технической спецификации (она у вас есть, верно?;)), у вас не должно возникнуть особых проблем.нет ничего плохого. Ответ очень прост: вы описываете функциональное тестирование, которое является важной частью обеспечения качества программного обеспечения. Тестирование внутренней реализации - это модульное тестирование, которое является другой частью QA программного обеспечения с другой целью. Вот почему вы чувствуете, что люди не согласны с вашим подходом.
Функциональное тестирование важно для подтверждения того, что система или подсистема делают то, что должны делать. Все, что видит клиент, должно быть протестировано таким образом.
Unit-test здесь, чтобы проверить, что 10 строк кода, которые вы только что написали, делают то, что должны. Это дает вам больше уверенности в вашем коде.
Оба они дополняют друг друга. Если вы работаете с существующей системой, возможно, первое, над чем стоит поработать, - это функциональное тестирование. Но как только вы добавите код, модульное тестирование тоже будет хорошей идеей.
У меня нет моей копии Лакоса передо мной, поэтому вместо того, чтобы цитировать, я просто укажу, что он справляется лучше, чем я объясню почему тестирование важно на всех уровнях.
Проблема с тестированием только «публичного поведения» заключается в том, что такой тест дает очень мало информации. Он обнаружит много ошибок (точно так же, как компилятор обнаружит много ошибок), но не может сказать вам, где они находятся. Плохо реализованный модуль часто возвращает хорошие значения в течение длительного времени, а затем перестает делать это при изменении условий; если бы этот модуль тестировался напрямую, тот факт, что он был реализован плохо, стал бы очевидным раньше.
Наилучший уровень детализации теста - это уровень модуля. Проведите тесты для каждого устройства через его интерфейс (ы). Это позволяет вам проверять и задокументировать ваши представления о том, как ведет себя каждый компонент, что, в свою очередь, позволяет вам тестировать зависимый код, тестируя только новые функциональные возможности, которые он вводит, что, в свою очередь, делает тесты короткими и целевыми. В качестве бонуса он сохраняет тесты с кодом, который они тестируют.
Другими словами, правильно тестировать только публичное поведение, если вы заметили, что каждый публично видимый класс имеет публичное поведение.
использовать относительный путь
главной страницы может быть: /index.html
дополнительная страница: Это аргумент, который следует сделать, чтобы быть хорошим программистом, вам нужно беспокоиться о крайних случаях, но чтобы быть хорошим тестером, вы одержимо беспокоитесь ;-) Кроме того, тестировщики могут быть дешевле, поэтому, возможно, стоит создать отдельную команду тестирования по этой причине.
Я думаю, что главный вопрос заключается в следующем: какая методология лучше всего подходит для поиска ошибок в программном обеспечении? Недавно я посмотрел видео (без ссылки, извините), в котором говорится, что рандомизированное тестирование дешевле и так же эффективно, как тесты, созданные человеком.
Вы не должны слепо думать, что модуль == класс. Я думаю, что это может быть контрпродуктивным. Когда я говорю, что пишу модульный тест, я тестирую логический модуль - «что-то», обеспечивающее определенное поведение. Единица может быть одним классом или несколькими классами, работающими вместе, чтобы обеспечить такое поведение. Иногда он начинается как отдельный класс, но позже становится тремя или четырьмя классами.
Если я начну с одного класса и напишу для него тесты, но позже он превратится в несколько классов, я обычно не буду писать отдельные тесты для других классов - это детали реализации в тестируемом модуле. Таким образом, я позволяю моему дизайну расти, и мои тесты не такие уж хрупкие.
Раньше я думал точно так же, как CrisW демонстрирует в этом вопросе - что тестирование на более высоких уровнях было бы лучше, но после того, как я получил некоторый опыт, мои мысли модерируются к чему-то между этим и «каждый класс должен иметь тестовый класс». Каждый модуль должен иметь тесты, но я предпочитаю определять свои модули немного иначе, чем когда-то. Это могут быть «компоненты», о которых говорит CrisW, но очень часто это также всего лишь один класс.
Кроме того, функциональные тесты могут быть достаточно хорошими, чтобы доказать, что ваша система делает то, что она должна делать, но если вы хотите Чтобы привести ваш дизайн в действие примерами / тестами (TDD / BDD), естественным следствием являются тесты нижнего рычага. Вы можете выбросить эти низкоуровневые тесты, когда закончите внедрение, но это будет пустой тратой - тесты являются положительным побочным эффектом. Если вы решите провести радикальный рефакторинг, делающий ваши низкоуровневые тесты недействительными, тогда вы выбросите их и один раз напишете новые.
Разделение цели тестирования / проверки вашего программного обеспечения и использования тестов / примеров для управления вашим дизайном / реализацией может прояснить это обсуждение много.
Обновление: Кроме того, есть два основных способа выполнения TDD: снаружи внутрь и наизнанку. BDD продвигает внешнее вовнутрь, что ведет к тестам / спецификациям более высокого уровня. Однако если вы начнете с деталей, вы напишете подробные тесты для всех классов.
Есть два основных способа выполнения TDD: снаружи внутрь и наизнанку. BDD продвигает внешнее вовнутрь, что ведет к тестам / спецификациям более высокого уровня. Однако если вы начнете с деталей, вы напишете подробные тесты для всех классов. Есть два основных способа выполнения TDD: снаружи внутрь и наизнанку. BDD продвигает внешнее вовнутрь, что ведет к тестированию / спецификациям более высокого уровня. Однако если вы начнете с деталей, вы напишете подробные тесты для всех классов.Функциональные тесты можно кодировать; Все в порядке. Но вам следует проверить, используя тестовое покрытие для реализации, чтобы продемонстрировать, что весь тестируемый код имеет цель относительно функциональных тестов и что он действительно делает что-то важное.
Я согласен с большинством сообщений здесь, однако я бы добавил следующее:
Первоочередной задачей является тестирование общедоступных интерфейсов, затем защищенных, а затем частных.
Обычно открытые и защищенные интерфейсы представляют собой совокупность частных и защищенных интерфейсов.
Лично: Вы должны все проверить. При наличии сильного набора тестов для небольших функций вы получите большую уверенность в том, что эти скрытые методы работают. Также я согласен с другим комментарием по поводу рефакторинга. Покрытие кода поможет вам определить, где находятся лишние биты кода, и при необходимости реорганизовать их.
Это зависит от вашего дизайна и от того, где будет наибольшая ценность. Один тип приложений может требовать другого подхода к другому. Иногда с помощью модульных тестов вы не уловите ничего интересного, тогда как функциональные / интеграционные тесты преподносят сюрпризы. Иногда модульные тесты терпят неудачу сотни раз во время разработки, выявляя множество ошибок в процессе разработки.
Иногда это тривиально. То, как некоторые классы связаны вместе, делает окупаемость вложений в тестирование каждого пути менее привлекательной, поэтому вы можете просто провести черту и перейти к более важным / сложным / часто используемым предметам.
Иногда недостаточно просто протестировать общедоступный API, потому что внутри скрывается некоторая особенно интересная логика, и приводить систему в движение и использовать эти конкретные пути слишком болезненно. Который' s, когда его внутренняя проверка окупается.
В наши дни я обычно пишу множество (часто чрезвычайно) простых классов, которые лучше всего справляются с одной или двумя вещами. Затем я реализую желаемое поведение, делегируя все сложные функции этим внутренним классам. Т.е. у меня есть несколько более сложные взаимодействия, но действительно простые классы.
Если я изменю свою реализацию и мне придется реорганизовать некоторые из этих классов, мне обычно все равно. Я стараюсь как можно лучше изолировать свои тесты, поэтому часто достаточно просто изменить, чтобы они снова заработали. Однако, если мне действительно приходится отбрасывать некоторые из внутренних классов, я часто заменяю несколько классов и вместо этого пишу несколько совершенно новых тестов. Я часто слышу, как люди жалуются на необходимость поддерживать тесты в актуальном состоянии после рефакторинга и, хотя иногда это неизбежно и утомительно, если уровень детализации достаточно хорош, обычно не имеет большого значения выбросить некоторые код + тесты.
Я считаю, что это одно из основных различий между дизайном, ориентированным на проверку, и отсутствием беспокойства.
Вы все еще придерживаетесь этого подхода? Я тоже считаю, что это правильный подход. Вы должны тестировать только общедоступные интерфейсы. Теперь общедоступный интерфейс может быть службой или каким-либо компонентом, который принимает входные данные из какого-либо пользовательского интерфейса или любого другого источника.
Но вы должны иметь возможность развивать дублирующую службу или компонент, используя подход Test First. т.е. определите общедоступный интерфейс и проверьте его на базовую функциональность. это не удастся. Реализуйте эту базовую функциональность с помощью API фоновых классов. Напишите API, чтобы удовлетворить только этот первый тестовый пример. Затем продолжайте спрашивать, что сервис может делать больше и развиваться.
Единственное сбалансированное решение, которое следует принять, - это разбить одну большую услугу или компонент на несколько меньших сервисов и компонентов, которые можно использовать повторно. Если вы твердо уверены, что компонент можно повторно использовать в разных проектах. Затем для этого компонента должны быть написаны автоматические тесты. Но опять же, тесты, написанные для большой службы или компонента, должны дублировать функционально уже протестированные компоненты.
Некоторые люди могут прийти к теоретической дискуссии о том, что это не модульное тестирование. Так что все в порядке. Основная идея - иметь автоматизированные тесты для тестирования вашего программного обеспечения. Так что, если это не на уровне единицы. Если он охватывает интеграцию с базой данных (которую вы контролируете), то это только лучше.
Дайте мне знать, если вы разработали какой-либо хороший процесс, который работает для вас .. с момента вашего первого сообщения ..
с уважением Амит