Так что тестирование с одним утверждением нарушает DRY?
Нет, но это способствует нарушению.
Тем не менее, хороший объектно-ориентированный дизайн имеет тенденцию выходить за рамки для модульных тестов - в основном по уважительной причине. Более важно, чтобы модульные тесты были изолированы друг от друга, чтобы тест можно было опросить изолированно и, если необходимо, зафиксировать с уверенностью, что вы не нарушите другие тесты. По сути, правильность и читаемость теста важнее его размера или удобства обслуживания.
Честно говоря, я никогда не был поклонником правила «одно утверждение для каждого теста» по причинам, которые вы описываете: это приводит к большому количеству шаблонного кода, который трудно читать, легко неправильно разбирать и трудно исправить, если вы будете проводить рефакторинг (что заставляет вас меньше заниматься рефакторингом).
Если функция должна возвращать список «foo» и «bar» для заданного ввода, но в любом порядке, вполне нормально использовать два утверждения, чтобы проверить, что оба они находятся в наборе результатов. Когда вы сталкиваетесь с проблемами, когда один тест проверяет два входа или два побочных эффекта, и вы не знаете, какой из двух вызвал сбой.
Я рассматриваю это как вариант Принципа единой ответственности: должно быть только одно, что может привести к провалу теста, и в идеальном мире это изменение должно нарушить только один тест.
Но в конце концов это компромисс. Вы с большей вероятностью потратите больше времени на поддержание всего копируемого кода, или же вы потратите больше времени на поиск первопричин, когда тесты могут быть нарушены несколькими источниками. Пока вы пишете "некоторые" тесты, это, вероятно, не имеет большого значения. Несмотря на мое пренебрежение к тестам с одним утверждением, я склонен ошибаться в сторону большего количества тестов. Ваш пробег может варьироваться.