﻿# Как статический анализ может дополнять юнит\-тестирование на примере NUnit

Довольно часто при обсуждении средств статического анализа для C\# проектов программисты пишут о том, что в этом нет необходимости, потому что с помощью юнит\-тестирования они отлавливают большинство ошибок\. Я решил проверить, насколько хорошо протестирован один из самых известных юнит\-тест фреймворков \- NUnit, и посмотреть найдёт ли там что\-нибудь наш анализатор\.

![0420_NUnit_ru/image1.png](https://import.viva64.com/docx/blog/0420_NUnit_ru/image1.png)

## Введение

NUnit \- это портированная с Java на C\# популярная библиотека для юнит\-тестирования \.NET проектов\. Исходный код открыт и доступен на сайте проекта [http://www\.nunit\.org/](https://nunit.org/)\.

Стоит отметить, что JUnit \- проект, с которого был портирован NUnit, создали такие известные программисты как Эрих Гамма \- один из авторов книги о шаблонах объектно\-ориентированного проектирования, и Кент Бек \- создатель методологий разработки через тестирование и экстремального программирования\. Я помню, как когда\-то читал его книгу Test Driven Development By Example, где он рассказывает о разработке через тестирование на примере создания тестового фреймворка, аналогичного JUnit, следуя всем своим методологиям\. То есть можно не сомневаться в том, что JUnit и NUnit разработаны в лучших традициях юнит\-тестирования, о чём так же говорит цитата Кента Бека на сайте NUnit: "\.\.\. великолепный пример идиоматического дизайна\. Большинство тех, кто портировал xUnit просто переносили версию для Smalltalk или Java\. То же самое сделали и мы с NUnit в первый раз\. Эта новая версия NUnit является такой, какой она должна была быть, если бы была написана на C\# с самого начала"\.

Я посмотрел исходники NUnit \- там очень много тестов, ощущение такое, что протестировано всё что только можно\. Учитывая отличный дизайн и тот факт, что NUnit используется тысячами разработчиков на протяжении многих лет, я думал, что PVS\-Studio не найдёт в нём ни одной ошибки\. Но нет, ошибка нашлась\.

## О найденной ошибке

Сработала диагностика [V3093](https://pvs-studio.ru/ru/docs/warnings/v3093/) о том, что иногда программисты вместо операторов && и \|\| используют операторы & и \|\. Проблема может возникнуть в том случае, когда важно чтобы правая часть выражения не выполнялась при определённых условиях\. Посмотрим, как эта ошибка выглядит в NUnit\.

```cpp
public class SubPathConstraint : PathConstraint
{
    protected override bool Matches(string actual)
    {
        return actual != null &
            IsSubPath(Canonicalize(expected), Canonicalize(actual));
    }
}
public abstract class PathConstraint : StringConstraint
{
    protected string Canonicalize(string path)
    {
        if (Path.DirectorySeparatorChar !=
            Path.AltDirectorySeparatorChar)
            path = path.Replace(Path.AltDirectorySeparatorChar,
                                Path.DirectorySeparatorChar);
        ....
    }
}
```

Даже если в метод _Matches_ в качестве параметра _actual_ придёт значение _null_, то правая часть оператора & всё равно будет вычислена, а значит будет вызван метод _Canonicalize_\. Если посмотреть его определение, то видно, что в нём значение параметра _path_ уже не проверяется на _null_, а сразу у него зовётся метод _Replace_, где и возможен потенциальный _NullReferenceException_\. Попробуем воспроизвести проблему\. Для этого я написал простой юнит\-тест:

```cpp
[Test]
public void Test1()
{
    Assert.That(@"C:\Folder1\Folder2", Is.SubPathOf(null));
}
```

Запускаем и смотрим результат:

![0420_NUnit_ru/image2.png](https://import.viva64.com/docx/blog/0420_NUnit_ru/image2.png)

Так и есть: NUnit упал с _NullReferenceException_\. Даже в таком хорошо протестированном продукте как NUnit статический анализатор PVS\-Studio смог найти реальную ошибку\. Отмечу, что сделать это мне было не сложнее, чем написать юнит\-тест \- нужно выбрать из меню проверку проекта и проанализировать грид с результатами\.

## Заключение

Юнит\-тесты и статический анализ \- это не исключающие, а дополняющие друг друга методики разработки программного обеспечения \[[1](https://pvs-studio.ru/ru/blog/posts/cpp/a0080/)\]\. [Скачайте](https://pvs-studio.ru/ru/pvs-studio/download/) статический анализатор PVS\-Studio и посмотрите не обнаружатся ли там ошибки, которые не были найдены юнит тестами\.

## Дополнительные ссылки

1. Андрей Карпов\. [Как статический анализ дополняет TDD](https://pvs-studio.ru/ru/blog/posts/cpp/a0080/)\.
1. Илья Иванов\. [Об одной интересной ошибке в Lucene\.Net](https://pvs-studio.ru/ru/blog/posts/csharp/0381/)\.