Unit test в разрезе паскаля

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

Unit test в разрезе паскаля

Сообщение Brainenjii » 16.03.2010 07:54:28

Последнее время часто слышу словосочетание "Unit test". Почитал википедию - штука вроде классная - часто после обновления куска кода получал мелкие глюки в совершенно неожиданных местах ^_^ Но как это реализовывать на fpc? Кто-нибудь пробовал?
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Unit test в разрезе паскаля

Сообщение Climber » 16.03.2010 09:50:55

Теория.
Юнит-тестированию лучше всего поддается код, написанный в функциональном стиле (см. функциональное программирование). То есть все параметры, от которых может зависеть результат работы функции, лучше передавать в нее в качестве аргументов. Это не всегда удается, но чем чаще, тем лучше.
Практика.
Есть модуль fpcunit в папке lazarus/components/fpcunit. Там лежит обычный пакет, после установки которого в меню "Создать" появляется пункт "fpcunit application". На freepascal.org есть файлик fpcunit.pdf, там мануал, могу скинуть. Пакет содержит набор классов для тестирования и гуи оболочку. Модуль является аналогом JUnit (java).
Climber
постоялец
 
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Re: Unit test в разрезе паскаля

Сообщение Brainenjii » 16.03.2010 10:26:01

Вы с ним работали? Насколько это применимо? ^_^ Сейчас смотрю на свой код - не представляю как это реализовать
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Unit test в разрезе паскаля

Сообщение Climber » 16.03.2010 11:59:39

Работал. Применимо. Осталось одолеть свою всепобеждающую лень и написать тесты на каждый чих в программе. Проблема в том, что написание теста занимает довольно много времени, а времени всегда не хватает. Ну и есть пара глюков - не глюков, но вопросов... Короче, тесты тоже надо тестировать - задавать заведомо провальные условия и смотреть, ругнется или нет. Некоторые из тамошних Assert'ов, как мне показалось, не работают.

Добавлено спустя 2 минуты 41 секунду:
Я даже пытался написать свою надстройку для тестирования GUI и реализации некоторых плюшек, которые давно появились в JUnit (например, выполнение нескольких тестов с общими SetUp и TearDown). Но что-то у меня заглохло это дело...
Climber
постоялец
 
Сообщения: 415
Зарегистрирован: 03.06.2007 20:09:57
Откуда: Москва

Re: Unit test в разрезе паскаля

Сообщение Brainenjii » 03.05.2011 09:11:29

Подниму тему ^_^
Почитал книжки, узнал забавную аббревиатуру TDD и снова вернулся в FPCUnit. Стало понятнее, даже заработало, но стало напрягать отсутствие интеграции с IDE. В описании к новому проекту FPCUnit Application сказано, что "Application source is automatically maintained by Lazarus", но не совсем понятно, как это самое automatically maintained добиться. Сейчас у меня два разных проекта - основной и тестовый. Тестовый использует модули основного, но писать так в стиле TDD почти невозможно - сборка тестового проекта запускает не основной, а, что характерно, тестовый...
Кто как пользуется FPCUnit?
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Unit test в разрезе паскаля

Сообщение vada » 04.05.2011 11:29:54

В JAVA всяческие IDE, типа (NetBeabs, Eclipse) код для JUtil тестов генерится одним нажатием пипки. Только потом подправить надо параметры для методов и что ожидаем получить. Кода генерит уйму. Руками столько писать, реально, влом. Ошибок вылавливается, на удивление, много. Совершенно в неожиданных местах. Основная это NulPointException. Это когда какая-то шняга в классе еще значения не получила, а ее уже юзать пытаемся. Такую ошибку можно поймать только при прогоне программы. Юнит тесты помогают почти автоматически их ловить.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Unit test в разрезе паскаля

Сообщение Brainenjii » 09.05.2011 10:49:16

А можно поконкретней - что именно генерируется автоматически? ^_^ Начал писать пакет к лазарю, интегрирующий FPCUnit в IDE, можно попробовать туда и автоматический генератор тестов (ну или шаблонов к тестам) приделать ^_^ https://github.com/Brainenjii/lazunit
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Unit test в разрезе паскаля

Сообщение vada » 10.05.2011 11:42:43

Ну вот из какого-то старого брошеного проекта.
Тестируется класс EntityBean таблицы базы данных PaperGroup
Код: Выделить всё
package ru.printbroker.model;
// Generated 20.10.2009 11:30:43 by Hibernate Tools 3.2.1.GA


import java.util.HashSet;
import java.util.Set;

/**
* Papergroup generated by hbm2java
*/
public class Papergroup  implements java.io.Serializable {


     private int pkPaperGroup;
     private String namePaperGroup;
     private Set papertypes = new HashSet(0);

    public Papergroup() {
    }

   
    public Papergroup(int pkPaperGroup) {
        this.pkPaperGroup = pkPaperGroup;
    }
    public Papergroup(int pkPaperGroup, String namePaperGroup, Set papertypes) {
       this.pkPaperGroup = pkPaperGroup;
       this.namePaperGroup = namePaperGroup;
       this.papertypes = papertypes;
    }
   
    public int getPkPaperGroup() {
        return this.pkPaperGroup;
    }
   
    public void setPkPaperGroup(int pkPaperGroup) {
        this.pkPaperGroup = pkPaperGroup;
    }
    public String getNamePaperGroup() {
        return this.namePaperGroup;
    }
   
    public void setNamePaperGroup(String namePaperGroup) {
        this.namePaperGroup = namePaperGroup;
    }
    public Set getPapertypes() {
        return this.papertypes;
    }
   
    public void setPapertypes(Set papertypes) {
        this.papertypes = papertypes;
    }
}

Для этого класса генерится тестовый класс, который вызывает все методы класса PaperGroup
Код: Выделить всё
/*
*
*
*/

package ru.printbroker.model;

import java.util.Set;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.*;

/**
*
* @author pikin
*/
public class PapergroupTest {

    public PapergroupTest() {
    }

    @BeforeClass
    public static void setUpClass() throws Exception {
    }

    @AfterClass
    public static void tearDownClass() throws Exception {
    }

    @Before
    public void setUp() {
    }

    @After
    public void tearDown() {
    }

    /**
     * Test of getPkPaperGroup method, of class Papergroup.
     */
    @Test
    public void testGetPkPaperGroup() {
        System.out.println("getPkPaperGroup");
        Papergroup instance = new Papergroup();
        int expResult = 0;
        int result = instance.getPkPaperGroup();
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    /**
     * Test of setPkPaperGroup method, of class Papergroup.
     */
    @Test
    public void testSetPkPaperGroup() {
        System.out.println("setPkPaperGroup");
        int pkPaperGroup = 0;
        Papergroup instance = new Papergroup();
        instance.setPkPaperGroup(pkPaperGroup);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    /**
     * Test of getNamePaperGroup method, of class Papergroup.
     */
    @Test
    public void testGetNamePaperGroup() {
        System.out.println("getNamePaperGroup");
        Papergroup instance = new Papergroup();
        String expResult = "";
        String result = instance.getNamePaperGroup();
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    /**
     * Test of setNamePaperGroup method, of class Papergroup.
     */
    @Test
    public void testSetNamePaperGroup() {
        System.out.println("setNamePaperGroup");
        String namePaperGroup = "";
        Papergroup instance = new Papergroup();
        instance.setNamePaperGroup(namePaperGroup);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    /**
     * Test of getPapertypes method, of class Papergroup.
     */
    @Test
    public void testGetPapertypes() {
        System.out.println("getPapertypes");
        Papergroup instance = new Papergroup();
        Set expResult = null;
        Set result = instance.getPapertypes();
        assertEquals(expResult, result);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

    /**
     * Test of setPapertypes method, of class Papergroup.
     */
    @Test
    public void testSetPapertypes() {
        System.out.println("setPapertypes");
        Set papertypes = null;
        Papergroup instance = new Papergroup();
        instance.setPapertypes(papertypes);
        // TODO review the generated test code and remove the default call to fail.
        fail("The test case is a prototype.");
    }

}


В тестовом классе в методах следует подправить значения, которые подставляются для вызовов методов... В данном варианте ничего не подправлено. Все в девственном виде после генерации.
И такие классы генерятся для всех классов указанного для генерации пакета. Потом генерится main класс из которого вызываются все тесты. Валится огромный лог из кторого выиискиваем какой метод у нас вернул false или exception. Разбираемся чёпочём....

Надеюсь, у паскалистов не будет проблем с чтением JAVA кода. :)
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Unit test в разрезе паскаля

Сообщение Brainenjii » 10.05.2011 12:05:53

А в процессе дополнения класса Papergroup - в тестовом классе автоматом появляются шаблоны новых тестов?
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Unit test в разрезе паскаля

Сообщение vada » 10.05.2011 12:15:53

А в процессе дополнения класса Papergroup - в тестовом классе автоматом появляются шаблоны новых тестов?


Нет. Надо перегенерить и поновой доработать напильником. Хотя... зуб не дам. Не приходилось серьезно класс ломать.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Unit test в разрезе паскаля

Сообщение Max Rusov » 10.05.2011 14:16:26

IMHO - ерунда какая-то. Какой смысл создавать по экземпляру для вызова каждого метода? Что так можно протестировать? Из этого "тестового" класса придется выкинуть 90% мусора и все значимые проверки писать руками - что мы имеем и без этих хлопот. Лишний раз показывает что вся эта "автоматизация" - от лукавого.
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Unit test в разрезе паскаля

Сообщение vada » 10.05.2011 14:38:48

Я привел самый простейший код. Чтоб понятно было что и как.
На самом деле даже такой тест совсем не ерунда. И в такой "ерунде" встречаются ошибки.
Есть такое понятие как правильность программы. Причем, правильность программы можно доказать математически.
Доказательство операется на положение что если на в ход блока подаются правильные данные и из блока выходят правильные данные то такой блок является правильным. Эти тесты в частности для этого и служат.
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Unit test в разрезе паскаля

Сообщение Max Rusov » 10.05.2011 16:45:53

Методы класса работают в совокупности, какой смысл проверять их на новом экземпляре? Например: get/set. Типично проверить, что get возвратил то, что перед этим установили через set; что крайние значения устанавливаются корректно, а значения выходящие за допустимый диапазон возбуждают корректные ошибки... Ничего подобного в приведенном примере и близко не наблюдается, 90% кода - мусор.

vada писал(а):Причем, правильность программы можно доказать математически.

Разница между теорией и практикой на практике гораздо глубже чем разница между теорией и практикой в теории...
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Unit test в разрезе паскаля

Сообщение vada » 11.05.2011 09:58:07

Разница между теорией и практикой на практике гораздо глубже чем разница между теорией и практикой в теории...

Только на практике ни один нормальный заказчик не пример работу без JUNIT тестов. :wink:
Аватара пользователя
vada
энтузиаст
 
Сообщения: 691
Зарегистрирован: 14.02.2006 13:43:17

Re: Unit test в разрезе паскаля

Сообщение Max Rusov » 11.05.2011 10:57:13

vada писал(а):Только на практике ни один нормальный заказчик не пример работу без JUNIT тестов. :wink:

Смешно.
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 21

Рейтинг@Mail.ru