вопрос по unit test'ам

AlbertTheII

Новичок
вопрос по unit test'ам

предположим нужно написать класс, который будет уметь рассчитывать процент на банковский вклад.
данный класс должен принимать во внимание разные параметры: размер процента, тип (месячный/годовой/другой), период капитализации, кол-во дней вклада, процент может быть сложный и т.д.

в конечном итоге, класс будет содержать базовый метод CalculateInterest. как построить систему тестирования ? нужно ли для каждого возможного варианта писать тест ? где хранить данные для теста: в самом коде теста или в базе данных ?
ссылки на релевaнтную документацию приветствуются.
10x
 
Напишите задачу по шагам. Первое... второе... третье.
Алгоритм, формулы, расчёты, результати виводимые скриптом должны придумовать Вы самостоятельно, а всё что касается проблем с написание скрипта можете обращаться на форум.

как построить систему тестирования
тестирования чего?
зачем?

Если Вам надо учитывать параметры выше перечислиные и считать процент на банковский вклад, это, ИМХО, делаеться одной простой функцией. Если я правильно понимаю Вашу задачу, то примерно так:
PHP:
// Данные для теста могут поступать из формы, файла, БД или любой для Вас удобной форме
$data= array();
$data[размер процента]=50;
$data[тип]=2;
$data[период капитализации]=1;
$data[дней вклада]=360;
$data[сложный процент]=20;

function НазваниеВашейФункции(размер процента,тип,период капитализации,дней вклада,сложный процент)
{
// Ваша формула
return размер процента/период капитализации*...-...+... и т.д.;
}

// Вызов функции
$v = НазваниеВашейФункции($data[размер процента],$data[тип],$data[период капитализации],$data[дней вклада],$data[сложный процент]);

// Хранение исходных данных
mysql_query("INSERT INTO `my_table` VALUES(".$val.")");
Если я не угадал, то уточните задачу и тогда обращайтесь.
Чем мог, тем помог.
 

zerkms

TDD infected
Команда форума
если не ошибаюсь, то прецедент практически "мануальный" и нечто подобное рассматривается в Addison.Wesley.Test-driven.development.by.Kent.Beck
 

AlbertTheII

Новичок
Возвращаясь к своему вопросу, пусть будет класс:
PHP:
class InterestCalculator
{
	protected $ClassVariables = array();

	function __contstructor($VariablesArray)
	{
		if($this->ValidateVariables($VariablesArray))
		{
			$this->ClassVariables = $VariablesArray;
		}
		else
		{
			throw new Exception($e);
		}		
	}

	protected function ValidateVariables($VariablesArray) {/*...*/}

	public function CalculateInterest() {/*...*/}
}
вопрос:
предположим я начал писать по системе test first, т.е. написал тест, который вызывает пустой метод CalcualteInterest и падает, далее я взял определённые параметеры, посчитал на бумажке, что должно получиться и реализовал метод CalculateInterest так, что он стал корректно работать с данными параметрами, но ... вдруг это случайность ? нужно ли тестировать каждый параметр участвующий в рассчёте из ClassVariables ? нужно ли писать тесты для ValidateVariables ?
 

denver

?>Скриптер
AlbertTheII
но ... вдруг это случайность ?
Чем больше тестов тем больше уверенности, но. Хорошо если бы они тестировали не однотипные расчеты (т.е. скажем 2% тела функции), а чтоб включали исключения и прочие нюансы. Например,в вашем случае нужно проверить 1) простой 2) сложный процент 3) месячный 4) годовой 5) другой,
плюс было бы неплохо 6) подсчет в високосный год (если есть нюансы) 7) в цикле из 100 случайных данных убедиться что процент никогда не опускается ниже нуля (тоже себе тест).
Итого покроется довольно большая площадь внутренних расчетов при меньшем количестве тестов, что и есть золотой серединой (правда минимизация тестов все же не самоцель,полезно не делать сложных тестов если можно его разбить на много маленьких)

нужно ли писать тесты для ValidateVariables ?
Вульгарно говоря: если в случае неправильных данных она делает throw new Exception (отсев ошибок программера) то не нужно, если же false и пр. (выявление ошибки пользователя) то нужно.

Поправьте кто если что не так.
 

AlbertTheII

Новичок
а входные данные для тестов где держать ? в теле теста хардкодед или в базе ?
 

whirlwind

TDD infected, paranoid
>Вульгарно говоря: если в случае неправильных данных она делает throw new Exception (отсев ошибок программера) то не нужно

Как раз нужно. Выброс исключения - это запланированное поведение класса. Если исключение не выброшено, значит что то не работает. Юнит-тест - это не тест алгоритма, это тест класса.

>а входные данные для тестов где держать ? в теле теста хардкодед или в базе ?

Называется фикстура. Вот именно для этой задачи

>который будет уметь рассчитывать процент на банковский вклад

достаточно в теле
 

zerkms

TDD infected
Команда форума
Чем больше тестов тем больше уверенности, но.
очень сомнительное утверждение. как показывает практика чем больше тестов (имею ввиду больше некоего разумного количества) тем они более хрупкими получаются
 

Alexandre

PHPПенсионер
нужно ли тестировать каждый параметр участвующий в рассчёте из ClassVariables ? нужно ли писать тесты для ValidateVariables ?
тестируется все от А...Я
на каждый метод пишем свой тест, или метод тестирующего класса.

а входные данные для тестов где держать ? в теле теста хардкодед или в базе ?
ИМХО. в теле теста
если это только класс расчета, то я бы построил такой тест, чтоб он не обращался к БД
если класс должен обращаться к БД, то нужно использовать оберту, а обертку уже заменить МокОбъектом....
т.е. максимально изолировать расчетный класс от БД - это правда уже не методология тестирования, а методология проектирвоания..
 

zerkms

TDD infected
Команда форума
тестируется все от А...Я
на каждый метод пишем свой тест, или метод тестирующего класса.
я полагаю что для подхода test-first такой метод не совсем приемлем. тестировать следует только те ситуации, которые теоретически могут возникнуть. именно таким образом будет получен минимально необходимый и максимально гибкий код
если это только класс расчета, то я бы построил такой тест, чтоб он не обращался к БД
если класс должен обращаться к БД, то нужно использовать оберту, а обертку уже заменить МокОбъектом....
имхо моки на БД - зло. только БД может показать, как должна реагировать БД в процессе работы
 

Shturm

Гигант мысли
только БД может показать, как должна реагировать БД в процессе работы
ИМХО, справедливо только в отношении объектов, работающих с БД напрямую. Для всех остальных - "БД" способна только на две реакции -
она либо возвращает ожидаемые данные, либо нет ;)
 

zerkms

TDD infected
Команда форума
Shturm
есть подозрения что в различных ситуациях один и тот же запрос может возвращать совершенно разные значения. в этом случае ваш тест сработает, а клиентский код - нет.
 

whirlwind

TDD infected, paranoid
>моки на БД - зло

Моки в прицнипе - зло. По крайней мере в php и по крайней мере из-за того, что не дают использовать type hinting. Примерно как тестировать двигательный аппарат, подсунув человеку вместо ног костыли. Сугубо ИМХО, конечно.
 

zerkms

TDD infected
Команда форума
Андрейка
разные ошибки могут быть причиной неверной работы с бд, которую товарищи предлагают пропускать, заменяя моком
 

AlbertTheII

Новичок
я взял simpletest как фреймворк для unit test'ов, он умеет вызывать класс для test casе и запускать все его методы начинающиеся с test. возвращаясь к своей ситуации, в test case классе я могу определить метод testCalculateInterest, но я для себя не могу решить как построить этот метод, можно так например

PHP:
public function testCalculateInterest()
{
	$Tests = array('...'); // hardcoded 
	foreach ($Tests as $TestNum => $TestData)
	{
		$Calculator = new InterestCalculator($TestData['InputData']);
		assertIdentical($Calculator->CalculateInterest(), $TestData['OutputData']);
        unset($Calculator);
	}
}
это логично ?
про бд я спросил только в смысле хранить ли там тесты или же в самом тесте, моки мне в данном случае не нужны.
 

zerkms

TDD infected
Команда форума
про бд я спросил только в смысле хранить ли там тесты или же в самом тесте
естественно тесты нужно хранить в фс, непосредственно в файлах
 

AlbertTheII

Новичок
Автор оригинала: zerkms
естественно тесты нужно хранить в фс, непосредственно в фйлах
при помощи базы можно централизованно управлять всем процессом тестирования.

а сама структура тестов нормальная ?
 
Сверху