Как Вы добавляете демонстрационные (фиктивные) данные к своим модульным тестам?

Хорошим доказательством того, что Checked Exception не нужны, являются:

  1. Много фреймворка, который делает некоторую работу для Java. Как Spring, который оборачивает исключение JDBC в непроверенные исключения, выбрасывая сообщения в журнал
  2. Множество языков, которые пришли после java, даже сверху на платформе java - они не используют их
  3. Проверенные исключения, это добрый прогноз о том, как клиент будет использовать код, который выдает исключение. Но разработчик, который пишет этот код, никогда не узнает о системе и бизнесе, в котором работает клиент кода. Например, методы Interfcace, которые вынуждают генерировать проверенное исключение. В системе существует 100 реализаций, 50 или даже 90 реализаций не выдают это исключение, но клиент все равно должен перехватить это исключение, если он ссылается на этот интерфейс. Эти 50 или 90 реализаций, как правило, обрабатывают эти исключения внутри себя, помещая исключения в журнал (и это хорошее поведение для них). Что нам с этим делать? Мне бы лучше иметь некоторую базовую логику, которая бы выполняла всю эту работу - отправлять сообщения в журнал. И если я, как клиент кода, почувствую, что мне нужно обработать исключение - я сделаю это. Я могу забыть об этом, верно, но если я использую TDD, все мои шаги покрыты, и я знаю, чего хочу.
  4. Другой пример, когда я работаю с I / O в Java, это заставляет меня проверять все исключения, если файл не существует? что мне с этим делать? Если он не существует, система не перейдет к следующему шагу. Клиент этого метода не получит ожидаемое содержимое из этого файла - он может обработать исключение времени выполнения, в противном случае я должен сначала проверить Checked Exception, поместить сообщение в журнал, а затем выбросить исключение из метода. Нет ... нет - я бы лучше сделал это автоматически с RuntimeEception, который делает это / загорается автоматически. Нет никакого смысла обрабатывать это вручную - я был бы рад, что увидел сообщение об ошибке в журнале (AOP может помочь с этим .. что-то, что исправляет Java). Если, в конце концов, я угадаю, что система должна показывать всплывающее сообщение конечному пользователю - я покажу это, не проблема.

Я был бы счастлив, если бы java предоставил мне выбор , что использовать при работе с основными библиотеками, такими как I / O. Like предоставляет две копии одних и тех же классов - один обернут в RuntimeEception. Тогда мы можем сравнить, что люди будут использовать . На данный момент, тем не менее, многим лучше пойти на какую-то платформу поверх Java или другой язык. Как и Скала, JRuby, что угодно. Многие просто верят, что СОЛНЦЕ было правильно.

10
задан Michal 8 July 2009 в 11:37
поделиться

4 ответа

Just to be clear, you need to differenciate between UNIT testing (test a module with no implied dependencies on other modules) and app testing (test parts of application).

For the former, you need a mocking framework (I'm only familiar with Perl ones, but i'm sure they exist in Java/C#). A sign of a good framework would be ability to take a running app, RECORD all the method calls/returns, and then mock the selected methods (e.g. the ones you are not testing in this specific unit test) using recorded data. Для хороших модульных тестов вы ДОЛЖНЫ издеваться над каждой внешней зависимостью - например, без обращений к файловой системе, без обращений к БД или другим уровням доступа к данным, если это не то, что вы тестируете, и т. Д.

Для последних - та же самая насмешливая структура полезно, плюс возможность создавать наборы тестовых данных (которые можно сбросить для каждого теста). Данные, которые будут загружены для тестов, могут находиться в любом автономном хранилище, из которого вы можете загрузить - файлы BCP для данных Sybase DB, XML, все, что вам нравится. Мы используем как BCP, так и XML.

Обратите внимание, что такого рода тестирование «данных нагрузочного теста в БД» ЗНАЧИТЕЛЬНО проще, если общая структура вашей компании допускает - или, скорее, применяет - API «Каково настоящее имя таблицы БД для этого псевдонима таблицы». Таким образом, вы можете заставить ваше приложение просматривать клонированный "тест"

1
ответ дан 3 December 2019 в 22:01
поделиться

Не отвечая напрямую на вопрос, но один из способов ограничить количество тестов, которые должны использовать фиктивные данные, - это использовать фреймворк для создания фиктивных объектов, которые можно использовать для имитации поведения любого зависимости, которые у вас есть в классе.

Я обнаружил, что, используя фиктивные объекты, а не конкретную конкретную реализацию, вы можете резко сократить объем реальных данных, которые вам нужно использовать, поскольку имитирующие объекты не обрабатывают данные, которые вы им передаете. Они просто работают именно так, как вы от них хотите.

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

1
ответ дан 3 December 2019 в 22:01
поделиться

Я использую шаблон репозитория и имею фиктивный репозиторий, который создается с помощью рассматриваемых модульных тестов, он предоставляет известный набор данных, который включает примеры, которые находятся в пределах и вне диапазона для различных полей.

Это означает, что я могу протестировать свой код без изменений, предоставив экземпляр репозитория из тестового модуля для тестирования или производственного репозитория во время выполнения (через внедрение зависимостей (Castle)).

Я не знаю хорошей веб-ссылки для этого, но я многому научился из книги Стивена Сандерсона Professional ASP.NET MVC 1.0, опубликованной Apress. Подход MVC, естественно, обеспечивает разделение проблем, необходимое для того, чтобы ваше тестирование могло работать с меньшим количеством зависимостей.

Основные элементы заключаются в том, что ваш репозиторий реализует интерфейс для доступа к данным, этот же интерфейс затем реализуется поддельным репозиторием, который вы создаете в своем тестовом проекте.

В моем текущем проекте у меня есть такой интерфейс:

namespace myProject.Abstract
{
    public interface ISeriesRepository
    {
        IQueryable<Series> Series { get; }
    }
}

] Это реализовано как мой репозиторий живых данных (с использованием Linq to SQL), а также как поддельный репозиторий, таким образом:

namespace myProject.Tests.Respository
{
    class FakeRepository : ISeriesRepository
    {
        private static IQueryable<Series> fakeSeries = new List<Series> {
            new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
            new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
            ...
            new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
        }.AsQueryable();

        public IQueryable<Series> Series
        {
            get { return fakeSeries; }
        }
    }
}

Затем создается экземпляр класса, потребляющего данные, передавая ссылку на репозиторий конструктору:

namespace myProject
{
    public class SeriesProcessor
    {
        private ISeriesRepository seriesRepository;

        public void SeriesProcessor(ISeriesRepository seriesRepository)
        {
            this.seriesRepository = seriesRepository;
        }

        public IQueryable<Series> GetCurrentSeries()
        {
            return from s in seriesRepository.Series
                   where s.openingDate.Date <= DateTime.Now.Date
                   select s;
        }
    }
}

Затем в моих тестах Я могу подойти к этому так:

namespace myProject.Tests
{
    [TestClass]
    public class SeriesTests
    {
        [TestMethod]
        public void Meaningful_Test_Name()
        {
            // Arrange
            SeriesProcessor processor = new SeriesProcessor(new FakeRepository());

            // Act
            IQueryable<Series> currentSeries = processor.GetCurrentSeries();

            // Assert
            Assert.AreEqual(currentSeries.Count(), 10);
        }

    }
}

Затем посмотрите CastleWindsor, чтобы узнать об инверсии подхода к управлению вашим живым проектом, чтобы ваш производственный код мог автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.

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

В моем текущем проекте у меня есть такой интерфейс:

namespace myProject.Abstract
{
    public interface ISeriesRepository
    {
        IQueryable<Series> Series { get; }
    }
}

Он реализован как мой репозиторий живых данных (с использованием Linq to SQL) и также фальшивый репозиторий, например:

namespace myProject.Tests.Respository
{
    class FakeRepository : ISeriesRepository
    {
        private static IQueryable<Series> fakeSeries = new List<Series> {
            new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
            new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
            ...
            new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
        }.AsQueryable();

        public IQueryable<Series> Series
        {
            get { return fakeSeries; }
        }
    }
}

Затем создается экземпляр класса, потребляющего данные, передавая ссылку на репозиторий конструктору:

namespace myProject
{
    public class SeriesProcessor
    {
        private ISeriesRepository seriesRepository;

        public void SeriesProcessor(ISeriesRepository seriesRepository)
        {
            this.seriesRepository = seriesRepository;
        }

        public IQueryable<Series> GetCurrentSeries()
        {
            return from s in seriesRepository.Series
                   where s.openingDate.Date <= DateTime.Now.Date
                   select s;
        }
    }
}

Затем в моих тестах я могу подойти к нему так:

namespace myProject.Tests
{
    [TestClass]
    public class SeriesTests
    {
        [TestMethod]
        public void Meaningful_Test_Name()
        {
            // Arrange
            SeriesProcessor processor = new SeriesProcessor(new FakeRepository());

            // Act
            IQueryable<Series> currentSeries = processor.GetCurrentSeries();

            // Assert
            Assert.AreEqual(currentSeries.Count(), 10);
        }

    }
}

Затем посмотрите CastleWindsor для инверсии подход к управлению вашим живым проектом, позволяющий производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.

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

В моем текущем проекте у меня есть такой интерфейс:

namespace myProject.Abstract
{
    public interface ISeriesRepository
    {
        IQueryable<Series> Series { get; }
    }
}

Он реализован как мой репозиторий живых данных (с использованием Linq to SQL) и также фальшивый репозиторий, например:

namespace myProject.Tests.Respository
{
    class FakeRepository : ISeriesRepository
    {
        private static IQueryable<Series> fakeSeries = new List<Series> {
            new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
            new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
            ...
            new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
        }.AsQueryable();

        public IQueryable<Series> Series
        {
            get { return fakeSeries; }
        }
    }
}

Затем создается экземпляр класса, потребляющего данные, передавая ссылку на репозиторий конструктору:

namespace myProject
{
    public class SeriesProcessor
    {
        private ISeriesRepository seriesRepository;

        public void SeriesProcessor(ISeriesRepository seriesRepository)
        {
            this.seriesRepository = seriesRepository;
        }

        public IQueryable<Series> GetCurrentSeries()
        {
            return from s in seriesRepository.Series
                   where s.openingDate.Date <= DateTime.Now.Date
                   select s;
        }
    }
}

Затем в моих тестах я могу подойти к нему так:

namespace myProject.Tests
{
    [TestClass]
    public class SeriesTests
    {
        [TestMethod]
        public void Meaningful_Test_Name()
        {
            // Arrange
            SeriesProcessor processor = new SeriesProcessor(new FakeRepository());

            // Act
            IQueryable<Series> currentSeries = processor.GetCurrentSeries();

            // Assert
            Assert.AreEqual(currentSeries.Count(), 10);
        }

    }
}

Затем посмотрите CastleWindsor для инверсии подход к управлению вашим живым проектом, позволяющий производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.

namespace myProject.Abstract
{
    public interface ISeriesRepository
    {
        IQueryable<Series> Series { get; }
    }
}

Это реализовано как мой репозиторий в реальном времени (с использованием Linq to SQL), так и как поддельный репозиторий, например:

namespace myProject.Tests.Respository
{
    class FakeRepository : ISeriesRepository
    {
        private static IQueryable<Series> fakeSeries = new List<Series> {
            new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
            new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
            ...
            new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
        }.AsQueryable();

        public IQueryable<Series> Series
        {
            get { return fakeSeries; }
        }
    }
}

Затем создается экземпляр класса, потребляющего данные, с передачей ссылки на репозиторий конструктору:

namespace myProject
{
    public class SeriesProcessor
    {
        private ISeriesRepository seriesRepository;

        public void SeriesProcessor(ISeriesRepository seriesRepository)
        {
            this.seriesRepository = seriesRepository;
        }

        public IQueryable<Series> GetCurrentSeries()
        {
            return from s in seriesRepository.Series
                   where s.openingDate.Date <= DateTime.Now.Date
                   select s;
        }
    }
}

Затем в в моих тестах я могу подойти к этому так:

namespace myProject.Tests
{
    [TestClass]
    public class SeriesTests
    {
        [TestMethod]
        public void Meaningful_Test_Name()
        {
            // Arrange
            SeriesProcessor processor = new SeriesProcessor(new FakeRepository());

            // Act
            IQueryable<Series> currentSeries = processor.GetCurrentSeries();

            // Assert
            Assert.AreEqual(currentSeries.Count(), 10);
        }

    }
}

Затем посмотрите на CastleWindsor, чтобы узнать об инверсии управления вашим живым проектом, чтобы ваш производственный код мог автоматически создавать экземпляр вашего живого репозитория через внедрение зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.

namespace myProject.Abstract
{
    public interface ISeriesRepository
    {
        IQueryable<Series> Series { get; }
    }
}

Это реализовано как мой репозиторий в реальном времени (с использованием Linq to SQL), так и как поддельный репозиторий, например:

namespace myProject.Tests.Respository
{
    class FakeRepository : ISeriesRepository
    {
        private static IQueryable<Series> fakeSeries = new List<Series> {
            new Series { id = 1, name = "Series1", openingDate = new DateTime(2001,1,1) },
            new Series { id = 2, name = "Series2", openingDate = new DateTime(2002,1,30),
            ...
            new Series { id = 10, name = "Series10", openingDate = new DateTime(2001,5,5)
        }.AsQueryable();

        public IQueryable<Series> Series
        {
            get { return fakeSeries; }
        }
    }
}

Затем создается экземпляр класса, потребляющего данные, с передачей ссылки на репозиторий конструктору:

namespace myProject
{
    public class SeriesProcessor
    {
        private ISeriesRepository seriesRepository;

        public void SeriesProcessor(ISeriesRepository seriesRepository)
        {
            this.seriesRepository = seriesRepository;
        }

        public IQueryable<Series> GetCurrentSeries()
        {
            return from s in seriesRepository.Series
                   where s.openingDate.Date <= DateTime.Now.Date
                   select s;
        }
    }
}

Затем в в моих тестах я могу подойти к этому так:

namespace myProject.Tests
{
    [TestClass]
    public class SeriesTests
    {
        [TestMethod]
        public void Meaningful_Test_Name()
        {
            // Arrange
            SeriesProcessor processor = new SeriesProcessor(new FakeRepository());

            // Act
            IQueryable<Series> currentSeries = processor.GetCurrentSeries();

            // Assert
            Assert.AreEqual(currentSeries.Count(), 10);
        }

    }
}

Затем посмотрите на CastleWindsor, чтобы узнать об инверсии управления вашим живым проектом, чтобы ваш производственный код мог автоматически создавать экземпляр вашего живого репозитория через внедрение зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.

namespace myProject.Tests
{
    [TestClass]
    public class SeriesTests
    {
        [TestMethod]
        public void Meaningful_Test_Name()
        {
            // Arrange
            SeriesProcessor processor = new SeriesProcessor(new FakeRepository());

            // Act
            IQueryable<Series> currentSeries = processor.GetCurrentSeries();

            // Assert
            Assert.AreEqual(currentSeries.Count(), 10);
        }

    }
}

Затем посмотрите на CastleWindsor, где можно найти подход к инверсии управления для вашего живого проекта, чтобы позволить производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.

namespace myProject.Tests
{
    [TestClass]
    public class SeriesTests
    {
        [TestMethod]
        public void Meaningful_Test_Name()
        {
            // Arrange
            SeriesProcessor processor = new SeriesProcessor(new FakeRepository());

            // Act
            IQueryable<Series> currentSeries = processor.GetCurrentSeries();

            // Assert
            Assert.AreEqual(currentSeries.Count(), 10);
        }

    }
}

Затем посмотрите на CastleWindsor, где можно найти подход к инверсии управления для вашего живого проекта, чтобы позволить производственному коду автоматически создавать экземпляр вашего живого репозитория посредством внедрения зависимостей. Это должно приблизить вас к тому месту, где вы должны быть.

13
ответ дан 3 December 2019 в 22:01
поделиться

Ваш код в том виде, в каком он написан, не компилируется. Я сделал несколько «предположений» о том, что вы хотели сделать, и изменил код.

Подводя итог, вы можете вызвать правильную функцию, явно указав тип параметра функции:

connect<double> (&GApp::foo);

Если методы соединения являются членами шаблона класса, то необходимо указать тип класса только один раз:

template <typename T> class A
{
public:
  template<class Arg1>
  void connect(void (T::*f)(Arg1)) 
  {
    //Do some stuff
  }

  void connect(void (T::*f)()) 
  {
    //Do some stuff
  }
};

class GApp
{
public:
    void foo() {}
    void foo(double d) {}
};


int main ()
{
  A<GApp> a;
  a.connect (&GApp::foo);            // foo ()
  a.connect<double> (&GApp::foo);    // foo (double)
}

UPDATE:

В ответ на новый пример кода передается вся информация. «Редким» случаем является 'signal_void ', поскольку здесь сигнал имеет аргумент шаблона, а функция-член - нет. Поэтому мы рассматриваем этот пример отдельно, и на этом все готово. Теперь компилируется следующее:

  • Если у вас есть база данных вашего программного обеспечения, Google для "NDBUnit". Это структура для вставки и удаления данных в базах данных для модульных тестов.
  • Если у вас нет базы данных, возможно, XML будет немного более гибким в таких системах, как excel.
1
ответ дан 3 December 2019 в 22:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: