Comments 15
В моем фреймворке так:
В группе тестов:
Переменная класса глобальная и при использовании в конструкторе регистрируется в глобальном списке функторов, который запускается в main
Мо фреймворк конечно не UnitCPP но идея использования вышла оттуда. Его как-то резко остановили поддерживать, а куда деваться с накопленным багажем. Я еще туда и проверку утечек памяти встроил — очень удобно оперативно отслежкосякиивать.
#include "TCppUnit.h"
int wmain(int argc, wchar_t* argv[])
{
CPPUNIT_TEST_PACKAGE_START;
{
if (!CallAllUnits(counters, fnMsg))
{
LogError(L"Could not pass post utility internal tests");
return -1;
}
}
CPPUNIT_TEST_PACKAGE_END;
}
В группе тестов:
#include "TCppUnit.h"
static class FourTests : public TCppUnit
{
private:
std::vector<size_t> m_listLocations;
public:
REGISTER_CLASS(FourTests, 4){} // FourTests - название группы тестов. 4 - порядок группы в общем тесте
virtual void TearsUp()
{
m_listLocations.clear();
}
void TestREVC() // Counting DNA Nucleotides
{
bool result = Test_CompStandOfDNA();
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Could not processed complimentary paires of DNA", true, result );
}
void TestHAMM() // Evolution as a Sequence of Mistakes
{
const char* set1 = "GAGCCTACTAACGGGAT";
const char* set2 = "CATCGTAATGACGGCCT";
size_t result = TDNA::GetHammingDistance( set1, set2 );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Must process complimentary paires of DNA", 7, result );
}
};
BEGIN_UNIT_REGISTATION(FourTests)
CPPUNIT_TEST(TestREVC)
CPPUNIT_TEST(TestHAMM)
END_UNIT_REGISTATION(FourTests);
Переменная класса глобальная и при использовании в конструкторе регистрируется в глобальном списке функторов, который запускается в main
Мо фреймворк конечно не UnitCPP но идея использования вышла оттуда. Его как-то резко остановили поддерживать, а куда деваться с накопленным багажем. Я еще туда и проверку утечек памяти встроил — очень удобно оперативно отслежкосякиивать.
(__COUNT__ мой компилятор не поддерживает).
А __LINE__?
что за компилятор? Может и нам надо?
По поводу:
Я не использовал BOOST_PP_COUNTER, но мне стало интересно. Насколько я понял, всё сводится к следующему:
Как, черт побери, работает BOOST_PP_COUNTER?! Даже на stackoverflow ответом на соответствующий вопрос является «magic».
Я не использовал BOOST_PP_COUNTER, но мне стало интересно. Насколько я понял, всё сводится к следующему:
// File counter.hpp
#ifndef COUNTER_H_
#define COUNTER_H_
// Начальное значение
#define COUNTER 0
// Файлик, при включении которого будет происходить
// прибавление еденицы к текущему значению и, вообще,
// вся магия
#define UPDATE_COUNTER() "counter_inc.hpp"
#endif
// File counter_inc.hpp
// Увеличиваем текущее значение,
// сохраняем во временную переменную
#define INC_COUNTER COUNTER + 1
// Удаляем старое значение,
// ниже будет определено новое
#undef COUNTER
// Грубо говоря, вся суть сводится к этому, но
// не так просто: текущее значение @INC_COUNTER
// разбирается на 10 разрядов (смотри
// boost\preprocessor\slot\detail\shared.hpp),
// которые потом собираются вместе в @COUNTER (
// смотри t_1_56_0\boost\preprocessor\slot\detail\counter.hpp):
// # if BOOST_PP_COUNTER_DIGIT_10
// # define BOOST_PP_COUNTER BOOST_PP_SLOT_CC_10(BOOST_PP_COUNTER_DIGIT_10, /*ещё разряды*/ BOOST_PP_COUNTER_DIGIT_1)
// # elif BOOST_PP_COUNTER_DIGIT_9
// ...
//
//
// Т.е. максимальное значение @BOOST_PP_COUNTER состоит
// из 10 разрядов: 999999999.
#if(INC_COUNTER == 0)
# define COUNTER 0
#elif(INC_COUNTER == 1)
# define COUNTER 1
// ...
#endif
// Удаляем временную переменную
#undef INC_COUNTER
// main.cpp
#include <iostream>
#include "counter.hpp"
#include UPDATE_COUNTER()
int main()
{
std::cout << COUNTER << std::endl;
}
У меня ощущение, что мы с вами смотрим в разные версии буста. Я вижу вот такой файл counter.hpp:
Он инклудит сам себя и файл def.hpp, который явно что-то делает, но вот только что — совершенно неясно
# /* **************************************************************************
# * *
# * (C) Copyright Paul Mensonides 2005. *
# * Distributed under the Boost Software License, Version 1.0. (See *
# * accompanying file LICENSE_1_0.txt or copy at *
# * http://www.boost.org/LICENSE_1_0.txt) *
# * *
# ************************************************************************** */
#
# /* See http://www.boost.org for most recent version. */
#
# ifndef BOOST_PREPROCESSOR_SLOT_COUNTER_HPP
# define BOOST_PREPROCESSOR_SLOT_COUNTER_HPP
#
# include <boost/preprocessor/slot/detail/def.hpp>
#
# /* BOOST_PP_COUNTER */
#
# define BOOST_PP_COUNTER 0
#
# /* BOOST_PP_UPDATE_COUNTER */
#
# define BOOST_PP_UPDATE_COUNTER() <boost/preprocessor/slot/detail/counter.hpp>
#
# endif
Он инклудит сам себя и файл def.hpp, который явно что-то делает, но вот только что — совершенно неясно
# * *
# * (C) Copyright Paul Mensonides 2002.
# * Distributed under the Boost Software License, Version 1.0. (See
# * accompanying file LICENSE_1_0.txt or copy at
# * http://www.boost.org/LICENSE_1_0.txt)
# * *
# ************************************************************************** */
#
# /* See http://www.boost.org for most recent version. */
#
# ifndef BOOST_PREPROCESSOR_SLOT_DETAIL_DEF_HPP
# define BOOST_PREPROCESSOR_SLOT_DETAIL_DEF_HPP
#
# /* BOOST_PP_SLOT_OFFSET_x */
#
# define BOOST_PP_SLOT_OFFSET_10(x) (x) % 1000000000UL
# define BOOST_PP_SLOT_OFFSET_9(x) BOOST_PP_SLOT_OFFSET_10(x) % 100000000UL
# define BOOST_PP_SLOT_OFFSET_8(x) BOOST_PP_SLOT_OFFSET_9(x) % 10000000UL
# define BOOST_PP_SLOT_OFFSET_7(x) BOOST_PP_SLOT_OFFSET_8(x) % 1000000UL
# define BOOST_PP_SLOT_OFFSET_6(x) BOOST_PP_SLOT_OFFSET_7(x) % 100000UL
# define BOOST_PP_SLOT_OFFSET_5(x) BOOST_PP_SLOT_OFFSET_6(x) % 10000UL
# define BOOST_PP_SLOT_OFFSET_4(x) BOOST_PP_SLOT_OFFSET_5(x) % 1000UL
# define BOOST_PP_SLOT_OFFSET_3(x) BOOST_PP_SLOT_OFFSET_4(x) % 100UL
# define BOOST_PP_SLOT_OFFSET_2(x) BOOST_PP_SLOT_OFFSET_3(x) % 10UL
#
# /* BOOST_PP_SLOT_CC_x */
#
# define BOOST_PP_SLOT_CC_2(a, b) BOOST_PP_SLOT_CC_2_D(a, b)
# define BOOST_PP_SLOT_CC_3(a, b, c) BOOST_PP_SLOT_CC_3_D(a, b, c)
# define BOOST_PP_SLOT_CC_4(a, b, c, d) BOOST_PP_SLOT_CC_4_D(a, b, c, d)
# define BOOST_PP_SLOT_CC_5(a, b, c, d, e) BOOST_PP_SLOT_CC_5_D(a, b, c, d, e)
# define BOOST_PP_SLOT_CC_6(a, b, c, d, e, f) BOOST_PP_SLOT_CC_6_D(a, b, c, d, e, f)
# define BOOST_PP_SLOT_CC_7(a, b, c, d, e, f, g) BOOST_PP_SLOT_CC_7_D(a, b, c, d, e, f, g)
# define BOOST_PP_SLOT_CC_8(a, b, c, d, e, f, g, h) BOOST_PP_SLOT_CC_8_D(a, b, c, d, e, f, g, h)
# define BOOST_PP_SLOT_CC_9(a, b, c, d, e, f, g, h, i) BOOST_PP_SLOT_CC_9_D(a, b, c, d, e, f, g, h, i)
# define BOOST_PP_SLOT_CC_10(a, b, c, d, e, f, g, h, i, j) BOOST_PP_SLOT_CC_10_D(a, b, c, d, e, f, g, h, i, j)
#
# define BOOST_PP_SLOT_CC_2_D(a, b) a ## b
# define BOOST_PP_SLOT_CC_3_D(a, b, c) a ## b ## c
# define BOOST_PP_SLOT_CC_4_D(a, b, c, d) a ## b ## c ## d
# define BOOST_PP_SLOT_CC_5_D(a, b, c, d, e) a ## b ## c ## d ## e
# define BOOST_PP_SLOT_CC_6_D(a, b, c, d, e, f) a ## b ## c ## d ## e ## f
# define BOOST_PP_SLOT_CC_7_D(a, b, c, d, e, f, g) a ## b ## c ## d ## e ## f ## g
# define BOOST_PP_SLOT_CC_8_D(a, b, c, d, e, f, g, h) a ## b ## c ## d ## e ## f ## g ## h
# define BOOST_PP_SLOT_CC_9_D(a, b, c, d, e, f, g, h, i) a ## b ## c ## d ## e ## f ## g ## h ## i
# define BOOST_PP_SLOT_CC_10_D(a, b, c, d, e, f, g, h, i, j) a ## b ## c ## d ## e ## f ## g ## h ## i ## j
#
# endif
Нет, он не инклудит сам себя, Вы смотрите файлы в папке
И файл
Файлы (и расположение) одинаковы в 2х версиях буста, которые у меня есть (1.55 и 1.56).
\boost\preprocessor\slot
.И файл
counter.hpp
(который у вас в комментарии) инклудит файл detail\counter.hpp
, а вот BOOST_PP_SLOT_CC_*
, который в def.hpp
, как раз «склеивает» разряды числа.Файлы (и расположение) одинаковы в 2х версиях буста, которые у меня есть (1.55 и 1.56).
Вообще когда совсем одолевает лень при написании тестов:
* пишем тесты с выводом в stdout, вроде такого:
* запускаем наше хозяйство с выводом в простой текстовый файл, и сохраняем его куда-нибудь в укромное место как «эталон»
* повторный запуск — сравниваем результат с эталонным файлом чем-то вроде diff
* обновляем тесты — обновляем эталон
А когда не лень делают так: github.com/danmar/cppcheck/blob/master/test/testtokenize.cpp
* пишем тесты с выводом в stdout, вроде такого:
puts("Testing feature 1...");
printf("%d\n", result);
* запускаем наше хозяйство с выводом в простой текстовый файл, и сохраняем его куда-нибудь в укромное место как «эталон»
* повторный запуск — сравниваем результат с эталонным файлом чем-то вроде diff
* обновляем тесты — обновляем эталон
А когда не лень делают так: github.com/danmar/cppcheck/blob/master/test/testtokenize.cpp
Посмотрите, как сделано в Cutter. Там вообще отсутствует регистрация тестов, так как эта проблема перекладывается на тест-раннер. Он тупо выдирает все символы, экспортированные из динамической библиотеки, которые начинаются на «test_».
Для embedded в неизменном виде такой вариант, конечно, не походит. И альтернатива, мне кажется, только во встраивании промежуточного кодогенератора в билд-систему. Но это хороший пример удобства для пользователя ценой сложности для разработчика. Особенно применительно к тестинг-фреймворкам, которые в идеале должны «просто работать» из коробки.
Для embedded в неизменном виде такой вариант, конечно, не походит. И альтернатива, мне кажется, только во встраивании промежуточного кодогенератора в билд-систему. Но это хороший пример удобства для пользователя ценой сложности для разработчика. Особенно применительно к тестинг-фреймворкам, которые в идеале должны «просто работать» из коробки.
Сторонний раннер тоже вариант, да.
А почему мой вариант не подходит для embedded? Что нужно изменить?
Я планирую его запускать в отладчике, поэтому printf'ы вообще можно убрать, на самом деле. Просто, если тест не проходит — while(1){;}. И отладчик останавливается как раз на проваленном тесте, это даже удобнее, чем искать по информации из лога.
А почему мой вариант не подходит для embedded? Что нужно изменить?
Я планирую его запускать в отладчике, поэтому printf'ы вообще можно убрать, на самом деле. Просто, если тест не проходит — while(1){;}. И отладчик останавливается как раз на проваленном тесте, это даже удобнее, чем искать по информации из лога.
Sign up to leave a comment.
Полуавтоматическая регистрация юнит-тестов на чистом С