Принятие модульного теста [закрывается]

Я удалил 1.2 и установил 1.1, но это не сработало.

Поскольку я использовал локальный SDK, установленный ранее, я удалил и переустановил 1.1 и установил SDK по новому пути.

После того, как я использовал SDK по новому пути, у меня больше нет этих ошибок.

И я обновил Android Studio до 1.2, а также у меня нет ошибок.

69
задан cwash 5 February 2013 в 19:33
поделиться

19 ответов

Tips:

Avoid writing procedural code

Tests can be a bear to maintain if they're written against procedural-style code that relies heavily on global state or lies deep in the body of an ugly method. If you're writing code in an OO language, use OO constructs effectively to reduce this.

  • Avoid global state if at all possible.
  • Avoid statics as they tend to ripple through your codebase and eventually cause things to be static that shouldn't be. They also bloat your test context (see below).
  • Exploit polymorphism effectively to prevent excessive ifs and flags

Find what changes, encapsulate it and separate it from what stays the same.

There are choke points in code that change a lot more frequently than other pieces. Do this in your codebase and your tests will become more healthy.

  • Good encapsulation leads to good, loosely coupled designs.
  • Refactor and modularize.
  • Keep tests small and focused.

The larger the context surrounding a test, the more difficult it will be to maintain.

Do whatever you can to shrink tests and the surrounding context in which they are executed.

  • Use composed method refactoring to test smaller chunks of code.
  • Are you using a newer testing framework like TestNG or JUnit4? They allow you to remove duplication in tests by providing you with more fine-grained hooks into the test lifecycle.
  • Investigate using test doubles (mocks, fakes, stubs) to reduce the size of the test context.
  • Investigate the Test Data Builder pattern.

Remove duplication from tests, but make sure they retain focus.

You probably won't be able to remove all duplication, but still try to remove it where it's causing pain. Make sure you don't remove so much duplication that someone can't come in and tell what the test does at a glance. (See Paul Wheaton's "Evil Unit Tests" article for an alternative explanation of the same concept.)

  • No one will want to fix a test if they can't figure out what it's doing.
  • Follow the Arrange, Act, Assert Pattern.
  • Use only one assertion per test.

Test at the right level to what you're trying to verify.

Think about the complexity involved in a record-and-playback Selenium test and what could change under you versus testing a single method.

  • Isolate dependencies from one another.
  • Use dependency injection/inversion of control.
  • Use test doubles to initialize an object for testing, and make sure you're testing single units of code in isolation.
  • Make sure you're writing relevant tests
    • "Spring the Trap" by introducing a bug on purpose and make sure it gets caught by a test.
  • See also: Integration Tests Are A Scam

Know when to use State Based vs Interaction Based Testing

True unit tests need true isolation. Unit tests don't hit a database or open sockets. Stop at mocking these interactions. Verify you talk to your collaborators correctly, not that the proper result from this method call was "42".

Demonstrate Test-Driving Code

It's up for debate whether or not a given team will take to test-driving all code, or writing "tests first" for every line of code. But should they write at least some tests first? Absolutely. There are scenarios in which test-first is undoubtedly the best way to approach a problem.

Resources:

108
ответ дан 24 November 2019 в 13:41
поделиться

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

Я хочу сказать, что многие из новых методов разработки программного обеспечения работают только при совместном использовании. В частности, MVC, ORM, IoC, модульное тестирование и Mocking. DDD (в современном примитивном смысле) и TDD / BDD более независимы, поэтому вы можете использовать их или нет.

1
ответ дан 24 November 2019 в 13:41
поделиться

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

Альтернативой является то, что когда ваш Изменения в структуре, вы не тестируете изменения. Или вы вообще не тестируете Framework. Это то, что вы хотите?

Вы можете попробовать рефакторинг вашего Framework, чтобы он состоял из более мелких частей, которые можно было протестировать независимо. Затем, когда ваша структура изменится, вы надеетесь, что либо (а) изменится меньше частей, либо (б) изменения в основном касаются способов составления частей. В любом случае вы сможете лучше повторно использовать и код, и тесты. Но здесь требуется настоящее интеллектуальное усилие; не ждите, что это будет легко.

1
ответ дан 24 November 2019 в 13:41
поделиться

Почему вам нужно менять модульные тесты каждый раз, когда вы вносите изменения в свою структуру? Разве не должно быть наоборот?

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

2
ответ дан 24 November 2019 в 13:41
поделиться

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

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

Когда вы приближаетесь к дате производства , вы будете счастливы, что прошли эти тесты, поверьте мне :)

1
ответ дан 24 November 2019 в 13:41
поделиться

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

Не делайте этого. сдавайся, пока это расстраивает, выгода будет реализована.

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

Не делайте этого. сдавайся, пока это расстраивает, выгода будет реализована.

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

Не делайте этого. сдавайся, пока это расстраивает, выгода будет реализована.

3
ответ дан 24 November 2019 в 13:41
поделиться

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

3
ответ дан 24 November 2019 в 13:41
поделиться

Хороший вопрос!

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

Я могу порекомендовать одну замечательную книгу, которая заслуживает того, чтобы ее выставить в счет как Шаблоны проектирования модульного тестирования

HTH

4
ответ дан 24 November 2019 в 13:41
поделиться

Я бы настаивал на том, чтобы вы придерживались TDD. Попробуйте проверить свою структуру модульного тестирования, проведите один RCA (анализ первопричин) с вашей командой и определите область.

Исправьте код модульного тестирования на уровне набора и не меняйте часто свой код, особенно имена функций или других модулей.

1233] Будете признательны, если вы хорошо поделитесь своим примером, и тогда мы сможем больше узнать о проблемной области?

4
ответ дан 24 November 2019 в 13:41
поделиться

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

8
ответ дан 24 November 2019 в 13:41
поделиться

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

Хорошая идея - попытаться классифицировать сбои, которые вы видите. Какие у вас проблемы? Например, это обслуживание тестов (например, их компиляция после рефакторинга!) Из-за изменений API, или это связано с изменением поведения API? Если вы видите шаблон, вы можете попробовать изменить дизайн производственного кода или лучше изолировать тесты от изменений.

Если изменение нескольких вещей приводит к неописуемым разрушениям в вашем наборе тестов во многих местах, вы можете сделать несколько вещей (большинство из них - просто общие советы по модульному тестированию): небольшие блоки кода. Извлечь интерфейсы или базовые классы, где это имеет смысл, так что единицы кода в них есть «швы». Чем больше зависимости, которые вы должны втянуть (или хуже, создать экземпляр внутри класса используя "новый"), тем более подвержены поменять код будет. Если каждый единица кода имеет несколько зависимости (иногда пара или совсем нет) тогда лучше изолированы от изменений.

  • Только когда-либо утверждать, на чем потребности. Не утверждайте на промежуточном уровне, случайное или несвязанное состояние. Дизайнер контракт и испытание по контракту (например, если вы тестируете метод выталкивания стека, не проверяйте свойство count после толкать - это должно быть в отдельный тест).

    Я вижу эту проблему совсем немного, особенно если каждый тест это вариант. Если что-то из этого случайные изменения состояния, он ломается все, что утверждает на нем (нужны ли утверждения или не).

  • Как и в обычном коде, используйте фабрики и конструкторы в ваших модульных тестах. Я узнал об этом, когда около 40 тестов потребовался обновленный вызов конструктора после изменения API ...

  • Не менее важно использовать передний дверь первая. Ваши тесты всегда должны используйте нормальное состояние, если оно доступно. Тестирование на основе взаимодействия использовалось только тогда, когда это необходимо (т.е. нет состояния для проверки).

  • В любом случае, суть в том, что я бы попытался выяснить, почему / где тесты ломаются, и перейти оттуда. Сделайте все возможное, чтобы защитить себя от перемен.

    12
    ответ дан 24 November 2019 в 13:41
    поделиться

    Тестируете ли вы достаточно маленькие блоки кода? Вы не должны видеть слишком много изменений, если вы не меняете фундаментально все в своем основном коде.

    Как только все станет стабильным, вы больше оцените модульные тесты, но даже сейчас ваши тесты подчеркивают степень изменений в вашей структуре

    Оно того стоит, придерживайтесь этого как можно лучше.

    19
    ответ дан 24 November 2019 в 13:41
    поделиться

    Иногда при разработке тестов TDD ставятся под сомнение дизайн самого приложения. Убедитесь, что ваши классы хорошо спроектированы, ваши методы выполняют только одно действие за раз ... При хорошем дизайне должно быть просто написать код для тестирования простых методов и классов.

    0
    ответ дан 24 November 2019 в 13:41
    поделиться

    Я сам думал над этой темой. Я очень убежден в ценности модульных тестов, но не в строгом TDD. Мне кажется, что до определенного момента вы, возможно, занимаетесь исследовательским программированием, и то, как вы делите вещи на классы / интерфейсы, нужно будет изменить. Если вы потратили много времени на модульные тесты для старой структуры классов, это увеличило инерцию против рефакторинга, было болезненно отбрасывать этот дополнительный код и т. Д.

    0
    ответ дан 24 November 2019 в 13:41
    поделиться

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

    Рассмотрите возможность использования рефакторинга метода extract для выдергивать небольшие блоки кода, которые делают одно и только одно; без зависимостей и напишите свои тесты на эти небольшие методы.

    1
    ответ дан 24 November 2019 в 13:41
    поделиться

    Разве ваши модульные тесты не слишком ориентированы на черный ящик? Я имею в виду ... позвольте мне привести пример: предположим, вы тестируете какой-то контейнер, используете ли вы метод контейнера get () для проверки того, что новый элемент действительно был сохранен, или вам удается получить дескриптор фактического хранилища для извлечения товар прямо где он хранится? Последний делает хрупкие тесты: когда вы меняете реализацию, вы нарушаете тесты.

    Вы должны тестировать интерфейсы, а не внутреннюю реализацию.

    И когда вы меняете фреймворк, вам лучше попробовать сначала изменить тесты, а затем фреймворк.

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

    Вы должны тестировать интерфейсы, а не внутреннюю реализацию.

    И когда вы меняете фреймворк, вам лучше попробовать сначала изменить тесты, а затем фреймворк.

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

    Вы должны тестировать интерфейсы, а не внутреннюю реализацию.

    И когда вы меняете фреймворк, вам лучше попробовать сначала изменить тесты, а затем фреймворк.

    1
    ответ дан 24 November 2019 в 13:41
    поделиться

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

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

    Однако с хорошо подготовленными тестами на основе разработчиков вы также сможете проверить целостность системы.

    Надеюсь, это поможет.

    1
    ответ дан 24 November 2019 в 13:41
    поделиться

    Если проблема в том, что ваши тесты устаревают с фактическим кодом, вы можете сделать одно или оба из следующих:

    1. Обучите всех разработчиков не проходить проверку кода, который не обновить модульные тесты.
    2. Настройте автоматическое тестовое окно, которое запускает полный набор модульных тестов после каждой регистрации и отправляет электронные письма тем, кто нарушает сборку. (Раньше мы думали, что это только для «больших парней», но мы использовали пакет с открытым исходным кодом на выделенной коробке.)
    4
    ответ дан 24 November 2019 в 13:41
    поделиться

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

    • Использование конкретных классов вместо интерфейсов
    • Использование одиночных объектов
    • Вместо вызова множества статических методов для бизнес-логики и доступа к данным методов интерфейса

    Из-за этого я обнаружил, что обычно мои тесты ломались - не из-за изменения в тестируемом классе, а из-за изменений в других классах, которые вызывали тестируемый класс. В основном, рефакторинг классов для запроса их зависимостей данных и тестирование с помощью имитирующих объектов (EasyMock et al для Java) делает тестирование более целенаправленным и удобным в обслуживании. Мне очень понравились некоторые сайты, особенно по этой теме:

    2
    ответ дан 24 November 2019 в 13:41
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: