У вас есть порядок смешивания ваших петель; они считаются вложенными слева направо, поэтому for r in a[g]
представляет собой внешний цикл и выполняется первым. Поменяйте петли:
print [r['n'] for g in good for r in a[g]]
Теперь g
определен для следующего цикла for r in a[g]
, и выражение больше не вызывает исключение:
>>> a={
... 1: [{'n': 1}, {'n': 2}],
... 2: [{'n': 3}, {'n': 4}],
... 3: [{'n': 5}],
... }
>>> good = [1,2]
>>> [r['n'] for g in good for r in a[g]]
[1, 2, 3, 4]
В моем (ограниченном) опыте первая опция вполне немного более безопасна. В тестовом сценарии Вы только тестируете предопределенный вход и сравниваете результат, это работает хорошо, пока каждый возможный пограничный случай был проверен. Первая опция просто проверяет каждый вход и таким образом тестирует 'живые' значения, это отфильтровывает ошибки, реальные быстро, однако это идет с потерей производительности.
В Коде Полный Steve McConnell изучает нас, первый метод может использоваться успешно для отфильтровывания ошибок в отладочная сборка. В сборке конечных версий можно отфильтровать все утверждения (например, с флагом компилятора) для получения дополнительной производительности.
По-моему, лучший способ состоит в том, чтобы использовать оба метода:
Метод 1 для ловли недопустимых значений
int doWonderfulThings(const int* fantasticData)
{
ASSERT(fantasticData);
ASSERTNOTEQUAL(0, fantasticData)
return WOW_VALUE / fantasticData;
}
и метод 2 для тестирования пограничных случаев алгоритма.
int doMoreWonderfulThings(const int fantasticNumber)
{
int count = 100;
for(int i = 0; i < fantasticNumber; ++i) {
count += 10 * fantasticNumber;
}
return count;
}
TEST(TDD_Enjoy)
{
// Test lower edge
ASSERT_EQ(0, doMoreWonderfulThings(-1));
ASSERT_EQ(0, doMoreWonderfulThings(0));
ASSERT_EQ(110, doMoreWonderfulThings(1));
//Test some random values
ASSERT_EQ(350, doMoreWonderfulThings(5));
ASSERT_EQ(2350, doMoreWonderfulThings(15));
ASSERT_EQ(225100, doMoreWonderfulThings(150));
}
Оба механизма имеют значение. Любая достойная среда тестирования поймает стандарт, утверждают () так или иначе, таким образом, тестовый прогон, который заставляет утверждение перестать работать, приведет к проваленному тесту.
У меня обычно есть серия, утверждает в начале каждого метода C++ с комментарием '//предварительные условия; это - просто проверка работоспособности на состоянии, которое я ожидаю объект иметь, когда метод назовут. Они соответствуют приятно в любую платформу TDD, потому что они не только работают во времени выполнения, когда Вы тестируете функциональность, но и они также работают в тестовое время.
Нет никакой причины, почему Ваш пакет тестов не может поймать, утверждает, такие как тот в doMoreWonderfulThings. Это может быть сделано или при наличии Вашего УТВЕРЖДАТЬ, что обработчик поддерживает механизм обратного вызова, или Ваш тест утверждает, содержат блок попытки/выгоды.
Я не знаю, какое particlar подсообщество TDD Вы отсылаете к, но шаблоны TDD, я столкнулся с любым использованием, Утверждают. AreEqual () для положительных результатов или иначе используют механизм ExpectedException (например, атрибуты в.NET) для объявления ошибки, которая должна наблюдаться.