Russian Qt Forum
Ноябрь 23, 2024, 20:36 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [Решено] Прикручивание фреймворка CppUnit к Qt  (Прочитано 12580 раз)
8Observer8
Гость
« : Апрель 05, 2014, 13:08 »

Добавил 4/30/2014 07:40 PM
Фреймворк CppUnit уже давно не поддерживается и не развивается. К тому же, у него отсутствует возможность создавать Mock-объекты. Здесь инструкция по самому продвинутому TDD-фреймворку на C++ GTest - http://www.prog.org.ru/topic_26944_0.html


Привет!

Мне надо подсоединить к проекту внешние заголовочные файлы в Qt Creator из этой папки: C:/cygwin64/usr/include/cppunit/ Подскажите, пожалуйста, как это правильно сделать?

Я создал пустой проект.

В файле .pro я пишу:
Код
C++ (Qt)
HEADERS += C:/cygwin64/usr/include/
 

В файле main.cpp
Код
C++ (Qt)
#include <cppunit/TestRunner.h>
 
int main() {
   return 0;
}
 

Но компилятор ругается:
Цитировать
main.cpp:1: error: cppunit/TestRunner.h: No such file or directory
 #include <cppunit/TestRunner.h>
                                            ^

Заранее спасибо за ответ!
« Последнее редактирование: Апрель 30, 2014, 06:44 от 8Observer8 » Записан
VPS
Гость
« Ответ #1 : Апрель 05, 2014, 13:46 »

Вместо "HEADERS" используйте "INCLUDEPATH".
Записан
8Observer8
Гость
« Ответ #2 : Апрель 05, 2014, 14:21 »

Спасибо! Но теперь я не могу понять, почему безобидное включение файла вызвало столько ошибок?

Записан
Bepec
Гость
« Ответ #3 : Апрель 05, 2014, 14:29 »

Потому что вы вместо разбора проблемы ищите решение Улыбающийся

Немного информации. Один заголовочный файл подключить можно прямым инклудом
Код:
#include "c:/cygwin/blabla/tuktuk.h"
Но если в нем содержатся инклуды других файлов, то выпадет куча ошибок, как и у вас, ибо компилятор не сможет найти нужные вам файлы.

Включил в IncludePath папку вы решите эту проблему, но столкнётесь с тем, что некоторые файлы у вас будут дублироваться и компилятор будет в недоумении - какой же файл брать.

Я не могу вам точно сказать что у вас там происходит (не знаток mingw), но на мой взгляд у вас дублирование инклудов Подмигивающий
Записан
8Observer8
Гость
« Ответ #4 : Апрель 05, 2014, 14:39 »

Спасибо большое! Скорее всего, Вы правы и возможно здесь конфликт cygwin64 и mingw. Тот заголовочный файл, который я подключаю, идёт в комплекте со набором инструментария cygwin64.

Как начать разбираться в этой проблеме? Я всего лишь хочу подключить заголовочный файл: C:/cygwin64/usr/include/cppunit/TestRunner.h и чтобы у меня сработал Build. Я вообще не понимаю, что происходит. Помогите, пожалуйста, понять проблему.

Это удивительно, что в инструментарии cygwin64 в модуле CppUnit есть заголовочный файл для Qt:  QtTestRunner.h И он нормально подключается (срабатывает построение):
Код
C++ (Qt)
SOURCES += \
   main.cpp
INCLUDEPATH += "C:/cygwin64/usr/include/"
 

main.cpp
Код
C++ (Qt)
#include <cppunit/ui/qt/QtTestRunner.h>
 
int main() {
   return 0;
}
 


« Последнее редактирование: Апрель 05, 2014, 15:08 от 8Observer8 » Записан
Bepec
Гость
« Ответ #5 : Апрель 05, 2014, 16:37 »

Подключить файл и использовать класс описанный в файле - неравнозначные вещи Улыбающийся

Если вам нужен 1 - его и подключайте Веселый
Записан
8Observer8
Гость
« Ответ #6 : Апрель 05, 2014, 17:08 »

Да там много файлов. Задумка была в переносе в Qt кода для тестирования (реализацию поддержки модуля CppUnit) из NetBeans 7.4. Для начала, вот этого файла:

newtestrunner.cpp
Код
C++ (Qt)
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/TestResult.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/TestRunner.h>
 
int main() {
   // Create the event manager and test controller
   CPPUNIT_NS::TestResult controller;
 
   // Add a listener that colllects test result
   CPPUNIT_NS::TestResultCollector result;
   controller.addListener(&result);
 
   // Add a listener that print dots as test run.
   CPPUNIT_NS::BriefTestProgressListener progress;
   controller.addListener(&progress);
 
   // Add the top suite to the test runner
   CPPUNIT_NS::TestRunner runner;
   runner.addTest(CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest());
   runner.run(controller);
 
   // Print test in a compiler compatible format.
   CPPUNIT_NS::CompilerOutputter outputter(&result, CPPUNIT_NS::stdCOut());
   outputter.write();
 
   return result.wasSuccessful() ? 0 : 1;
}
 

Дело в том, что QTest не поддерживает сравнения вещественных actual, expected и с погрешностью delta, как это сделано в CppUnit:
Код
C++ (Qt)
CPPUNIT_ASSERT_DOUBLES_EQUAL(expected, actual, delta);
 

Ещё QTest не умеет отлавливать исключения, а CppUnit умеет:
Код
C++ (Qt)
std::vector<int> v;
CPPUNIT_ASSERT_THROW( v.at( 50 ), std::out_of_range );
 

Так что придёться использовать свои костыли для QTest, а именно, выше названные сравнение вещественных чисел и отлавливание исключений.
« Последнее редактирование: Апрель 05, 2014, 17:17 от 8Observer8 » Записан
Bepec
Гость
« Ответ #7 : Апрель 05, 2014, 18:37 »

Вот ты б вместо попытки тестировать простое приложение, сделал бы одно сложное Веселый И сразу бы понял, что этот путь ведёт не к тупику, нет. Он ведёт к 90% тестов, 10% разработки Улыбающийся
Записан
8Observer8
Гость
« Ответ #8 : Апрель 05, 2014, 19:20 »

Тесты писать - это просто. Я имею ввиду функции, которые принимают и возвращают простые типы, строки. Они позволяют описать функцию в виде тестов, учесть все тонкости, граничные значения, возвращаемые ошибки (исключения). Если есть тесты, то писать саму функцию более безопасно, как и рефакторить её позже. Можно по тестам понять, как работать с функцией, если прошло время. И заказчику лучше отдавать протестированные классы вместе с тестами. И писать их - это совсем не в напряг. Я не пишу 100 тестов, а где-то в районе 10. На данном этапе развития, мне этого хватает.

Другое дело писать тесты для сложных приложений, которые работают с базами данных, сетями. В таких случаях надо, чтобы фреймворк поддерживал Mock-объекты. К сожалению, QTest и CppUnit их не поддерживают. Для этого надо интегрировать в Qt такие фреймворки, как например: Google Mock или Boost Mock. Но пока остановлюсь на минимуме, а именно на QTest и CppUnit.
« Последнее редактирование: Апрель 05, 2014, 19:30 от 8Observer8 » Записан
Bepec
Гость
« Ответ #9 : Апрель 05, 2014, 19:27 »

Бесполезно переубеждать Улыбающийся
За то время, пока вы изучаете тесты и ООП, я в своё время изучил С++ и написал довольно сложную программу Улыбающийся Тем самым положив начало своей карьере.
По моему разумению программист в 1 очередь должен уметь программировать. Описывать алгоритмы и по ним программировать. Всё остальное вторично, ибо служит либо для оптимизации или для проверки. Улыбающийся А вы без первого второе изучаете Улыбающийся А смысл?
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #10 : Апрель 05, 2014, 19:42 »

За то время, пока вы изучаете тесты и ООП
Да не нужно никакого времени для изучения тестов. И на их написание тоже много времени не надо. Улыбающийся
Вы автор кода, вы знаете, что от него хотите получить, это описываете в тестах. Потратить 10 минут на класс, что бы в любой момент знать, что он рабочий, не очень большая цена.
Записан
8Observer8
Гость
« Ответ #11 : Апрель 05, 2014, 19:45 »

Тестирование я уже освоил. Сначала тесты - потом содержимое функции. Мне это сильно помогает. Я чувствую себя уверенее. Надеюсь, что этот подход войдёт в мой несгораемый запас и будет привычкой. Как и привычка писать свои классы исключений, чтобы обрабатывать ошибки и писать тесты для проверки исключений. На этом этапе я Mock-объекты пока изучать не буду (ну может если свободное время появится).

Используя тесты и исключения, теперь я могу писать, писать и писать всё более сложные программы, описывать алгоритмы, по ним писать программы и т.д.

А тесты уже не изучаю, а просто ими пользуюсь. Всегда. Даже для самых простых методов Улыбающийся Даже для гетеров и сетеров Улыбающийся Это увлекательно, не могу от этого отказаться, как не переубеждайте Улыбающийся
Записан
8Observer8
Гость
« Ответ #12 : Апрель 22, 2014, 10:36 »

Вот ты б вместо попытки тестировать простое приложение, сделал бы одно сложное Веселый И сразу бы понял, что этот путь ведёт не к тупику, нет. Он ведёт к 90% тестов, 10% разработки Улыбающийся

TDD наоборот призвана экономить время. Я понял фишку методологии "Разработки через тестирования". Она почти не имеет ничего общего с модульным тестирование. Модульным тестированием занимается специальный отдел (не программисты). Они тестируют уже готовые модули. На модульное тестирование уходит очень много времени, так как надо написать очень большой набор тестов.

TDD же работает так:
- Сначала пишем заглушку для метода класса
- Пишем несколько тестов по принципу: входные значения метода, ожидаемый результат, вызов метода, сравнение выходного значения метода и ожидаемого результата. На это уходит пара десятков секунд (при условии, что человек это уже делал не раз)
- Запускаем тестирование и убеждаемся, что ни один тест не выполнился (метод же пока без реализации). Как говорят поклонники методологии TDD - полоса на 100% красная ( скорее всего, они так говорят Улыбающийся )
- Возвращаемся к методу и пишем его реализацию
- Запускаем тестирование и убеждаемся, что полоса полностью зелёная
- Если нам требуется ещё функциональность от нашего метода, то мы пишем ещё несколько тестов, запускаем тестирование, убеждаемся, что полоса не на 100% зелёная, дописываем реализацию метода, чтобы удовлетворить новые тесты, запускаем тестирование, убеждаемся, что полоса на 100% зелёная
- Теперь мы можем при желании отрефакторить код внутри метода. После внесённых изменений опять запускаем тесты и убеждаемся, что мы ничего не испортили
- Это удобно, когда кто-то из команды неправильно понял внутреннюю работу метода, внес изменения (например для оптимизации или\и улучшения читабельности) и нечаянно испортил функциональность. Этот же человек может запустить тесты и убедиться, что он испортил
- Это так же удобно, если от метода требуется новая функциональность, или надо добавить какую-то защиту (чтобы метод ожидаемо реагировал на некорректные входные данные) Мы можем дописать новые тесты, запустить тесты, дописать функциональность в метод, запустить тесты
- А то что к концу разработки класса(ов) создаётся небольшой набор тестов, который демонстрирует (хотя бы минимальную) работоспособность системы - я так понимаю, это приятный бонус.
- Разработчик изначально проектирует методы, которые "можно будет тестировать". Это облегчает работу отделу тестирования
« Последнее редактирование: Апрель 22, 2014, 10:38 от 8Observer8 » Записан
Bepec
Гость
« Ответ #13 : Апрель 22, 2014, 11:03 »

Вопрос - как вы будете искать неполадку в программе, если все тесты зелёные? Проблема TDD в том, что вы пишете реализацию и проверяете её на 1 массиве данных. А если она на числе 102 даёт ошибку? Или же как проверить работоспособность метода, который использует метод?

PS последнее из моей практики - на числах от 200 до 255 выдаёт неверное значение. Вроде бы просто, но тогда тесты у вас должны учитывать все варианты ошибок )
Записан
OKTA
Гость
« Ответ #14 : Апрель 22, 2014, 12:01 »

Что-то я до сих пор не могу догнать философию этого тестирования  В замешательстве
Если, к примеру, метод возвращает и принимает int, то что он еще может вернуть и принять, кроме int? А если могут быть какие-то конкретные значения 1, 10, 28, 30 и т.д., то это же надо проверять в самом методе  Непонимающий Зачем тогда тут тесты?  Непонимающий
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.17 секунд. Запросов: 23.