Pull to refresh

Comments 6

Где именно?

Я слышал только об одном Code Contract — библиотека от MS, которая, кажется, скоро должна выйти. Давно не смотрел, что же она в итоге умеет. Потому что когда ее только объявили, я увидел, что это просто развитие идеи Design-by-Contract от Billy McCafferty — devlicio.us/blogs/billy_mccafferty/archive/2006/09/22/design_2d00_by_2d00_contract_3a00_-a-practical-introduction.aspx. А до него, кстати, это было в языке Eiffel.

В общем, если под Code Contract подразумевается явное указание того, какие данные требуются на входе и выходе метода, то это не интеграционное тестирование. У меня такие проверки есть — класс Utils.Common.Check. Эти проверки не предназначены для тестирования системы — это скорее защита программы от некорректных данных.
Да, это реализация design-by-contract для дотнет. Она, кстати, уже входит в дистрибутив версии 4.0.

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

Тесты, как я понимаю, у Вас пишутся вручную, а не генерируются по спецификациям, в Code Contracts тоже не генерируются.

Есть ещё инструмент NModel, он умеет генерировать тестовые последовательности по FSM-моделям. Его можно использовать в сочетании с контрактами, и, думаю, с Вашим фреймворком тоже.

У Code Contracts есть неприятная особенность — при нарушении контракта очень сложно понять, что именно нарушено. Может быть Вам удастся сделать свой фреймворк более дружелюбным, это было бы здорово.
М… Фактически тесты генерируются по спецификациям. Вручную нужно написать:
— спецификации.
— get акксессор, если для свойства он еще не определен.
— дескриптор свойства, если для данного типа свойств он еще не определен.

У меня в последнем проекте такая статистика:
— 56 спецификаций, в которых в сумме проверяется 216 свойств
— 21 аксессор
— 3 пользовательских дескриптора

Фактически тестом можно считать одно проверяемое свойство в спецификации. Тест генерируется из ожидаемых данных спецификации, действительных данных из аксессора и логики сопоставления из дескриптора.

Не знаю как сделано в Code Contract, но в Design By Contract проверка выглядит примерно так (проверки в статическом классе Check):

public double GetParameter( Vector point )
{
    Check.Require( !Direction.IsZeroLength, "Направление линии не должно быть вырожденным" );

    var t = new List<double>( 2 );

    // Параметры t по значимым осям
    if( Op.Nz( Direction.X ) )
    {
        t.Add( ( point.X - Begin.X ) / Direction.X );
    }
    if( Op.Nz( Direction.Y ) )
    {
        t.Add( ( point.Y - Begin.Y ) / Direction.Y );
    }

    // Проверка на то что параметр t существует и корректен
    Check.Ensure( t.Count > 0, "Если точка лежит на линии, то у нее должен быть определен параметр" );
    Check.Ensure( Op.Eq( t.Max( ), t.Min( ) ), "Разброс значений параметра t не должен быть больше заданной точности" );

    // Возвращаем среднее значение
    return t.Average( );
}


Своей цели обезопасить программу от неверных данных он служит. Мне Design By Contract в таком виде нравится.
Это классика же, все конверторы, компиляторы, и всевозможные тулзы такого типа так и тестируются. Такой подход оправдывает себя когда данные можно легко вынети за код и одним и тем же кодом проверять много различных кейсов за счет разных входных и выходных данных.
Sign up to leave a comment.

Articles