google web font

воскресенье, 18 марта 2012 г.

Про важность статического анализа

Есть ряд багов, которые нельзя поймать ни тестами, ни тестировщиками. Потому что формально установить наличие ошибки по выхлопу нельзя. Собственно, настоящие, красивые, баги появляются именно так, а не так, как мы уже привыкли: те "баги", которые мы видим каждый день — это либо дефекты выбранного алгоритма, либо его "забытые" тёмные закоулки (необработанные ошибки, нереализованные ветвления, неосвобождённая память и т.п.). А эти ошибки можно найти только анализируя код. И даже если это будет не тот "настоящий, красивый баг", которым можно восхищаться годами, постоянно переоткрывая его в багзилле, но тоже может быть интересно.

Вот простой пример:
sub very_bin_integer($) {
    my $length = int(shift) or die "Illegal length";
    my $ret = '';
    for ( 1 .. $length )
    {
        my $n = 0;
        while ( not $n ) {   
            $n = int(rand(9));
        };
        $ret .= $n;
    }
    return $ret;
}
Даже обработка некорректного ввода есть. Кто напишет корректный юнит-тест на эту ошибку — может рассчитывать на пирожок.
А кто найдёт тут две ошибки — ещё и на булку. Не буду понтоваться и рассказывать, что за ошибка и как её исправить, хе-хе. Зато могу привести ещё одни пример, который тоже ни юнит-тестом не поймаешь, ни вручную не найдёшь, потому что быдлокод эти инструменты не ловят принципиально (как и проблемы безопасности, к которым приводила предыдущая ошибка, хотя в тех областях, где она могла бы "выстрелить", таких ошибок не допускают, во всяком случае, случайно).
sub submit {
    my $self = shift;
    my $success = 0;
    for ( my $i = 0; $i < 10; $i++ ) {
        try {
            my $unique_mnemonic = $self->util->generate_random_string;
            $self->set_mnemonic($unique_mnemonic);
            $self->create;
            $success = 1;
            last;
        } otherwise { };
    }
    if ( !$success ) {
        throw CreationFailedException "Internal Error";
    }
}
Этот код пытается создать для объекта уникальный текстовый идентификатор и проверяет его уникальность, испытывая на прочность базу данных с уникальным индексом по соответствующему полю. Код даёт себе 10 попыток, если не повезло — то увы. Хитрость в том, что вероятность провалить все десять попыток здесь гораздо выше вероятности того, что этот код когда-нибудь исправят. Даже когда это исключение вылетает оператору прямо в браузер, он нажимает "назад", снова нажимает "создать" и приходит к выводу, что ему просто показалось. Попробуй, напиши на это юнит-тест. Попробуй убедить программера, который столько лет прожил под виндой, что это проблема, тем более, что оператор про неё уже забыл.
Ещё хороший пример бага, на который нельзя написать юнит-тест — это шаффл списка по "методу единой россии". Да и вообще, что бы мы делали, если бы тестировщикам только чёрные ящики на тестирование давали?

Комментариев нет:

Отправить комментарий