Перем ИмяМетода Экспорт;

Перем _фПропускТестаОтключен; 

Функция Конт(Конт) Возврат Конт; КонецФункции
Функция Сам() Возврат Конт(Контекст); КонецФункции

Процедура Сетап() Экспорт
	// virtual method
КонецПроцедуры

Процедура Сброс() Экспорт
	// virtual method
КонецПроцедуры

Функция Описание() Экспорт
	Возврат ТипЗначенияСтр(Сам())+"::"+ИмяМетода;
КонецФункции
//--------------------------------------------

Функция Завершен() Экспорт
	Возврат 1;
КонецФункции
//--------------------------------------------

Процедура Запустить(Результат, фОтключитьПропуск) Экспорт
	_фПропускТестаОтключен=фОтключитьПропуск;
	Сам().Сетап();

	Длг = СоздатьОбъект("Делегат");
	Длг.ОпределитьТип(0, 0);

	Состояние(Описание());
	Попытка
		Длг.Добавить(Сам(), ИмяМетода);
		Длг.Вызвать();
		Результат.ДобавитьУспех();
	Исключение
		Ошибка=ОписаниеОшибки();
		Результат.ДобавитьПадение(Описание(), Ошибка, Сам().ПолучитьИсключение());
	КонецПопытки;

	Сам().Сброс();
	Состояние("");
КонецПроцедуры

Процедура Инит(ИмяТестовогоМетода) Экспорт
	ИмяМетода = ИмяТестовогоМетода;
КонецПроцедуры

Процедура ПропуститьТест(фФатальнаяОшибка, Причина) Экспорт
	Если фФатальнаяОшибка=0 Тогда
		Если _фПропускТестаОтключен=1 Тогда Возврат; КонецЕсли;
	КонецЕсли;
	Искл=СоздатьОбъект("Исключение_ПропуститьТест");
	Искл.Причина=Причина;
	Сам().ВыброситьИскл(Искл);
КонецПроцедуры

Процедура Assert(Значение) Экспорт
	Если ПустоеЗначение(Значение)=0 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = "<"+Значение+"> - ложно, а хотели истину.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура AssertNot(Значение) Экспорт
	Если ПустоеЗначение(Значение)=1 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = "<"+Значение+"> - истинно, а хотели ложь";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура AssertEquals(Значение1, Значение2) Экспорт
	Если Значение1 = Значение2 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = "<"+Значение1+"> не равно <"+Значение2+">, а хотели, чтоб было равно.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура AssertEqualsWithPrecision(Значение1, Значение2, Точность) Экспорт
	AssertEquals(Окр(Значение1, Точность), Окр(Значение2, Точность));
КонецПроцедуры

Процедура AssertNotEquals(Значение1, Значение2) Экспорт
	Если Значение1 <> Значение2 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = "<"+Значение1+"> равно <"+Значение2+">, а хотели, чтоб было не равно.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура ПроверитьИстину(Значение) Экспорт
	Assert(Значение);
КонецПроцедуры

Процедура ПроверитьЛожь(Значение) Экспорт
	AssertNot(Значение);
КонецПроцедуры

Процедура ПроверитьРавенство(Значение1, Значение2) Экспорт
	AssertEquals(Значение1, Значение2);
КонецПроцедуры

Процедура ПроверитьРавенствоСТочностью(Значение1, Значение2, Точность) Экспорт
	AssertEqualsWithPrecision(Значение1, Значение2, Точность);
КонецПроцедуры

Процедура ПроверитьНеравенство(Значение1, Значение2) Экспорт
	AssertNotEquals(Значение1, Значение2);
КонецПроцедуры

Процедура ПроверитьРавенствоДлинныхСтрок(Строка1, Строка2, НеУчитыватьРазноеКоличествоСтрок = 0) Экспорт
	Если Строка1 = Строка2 Тогда Возврат; КонецЕсли;
	
    КолСтрок = СтрКоличествоСтрок(Строка1);
	Если НеУчитыватьРазноеКоличествоСтрок = 1 Тогда
		КолСтрок = Мин(СтрКоличествоСтрок(Строка1), СтрКоличествоСтрок(Строка2))
	Иначе
		ПроверитьРавенство(СтрКоличествоСтрок(Строка1), СтрКоличествоСтрок(Строка2));
	КонецЕсли;
	Для к=1 По КолСтрок Цикл
		Стр1 = СтрПолучитьСтроку(Строка1, к);
		Стр2 = СтрПолучитьСтроку(Строка2, к);
		ПроверитьРавенство(к+": "+Стр1, к+": "+Стр2);
	КонецЦикла;
КонецПроцедуры

Процедура ПроверитьБольше(Значение1, Значение2) Экспорт
	Если Значение1 > Значение2 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = ""+Значение1+" <= "+Значение2+", а хотели, чтоб было больше.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура ПроверитьМеньше(Значение1, Значение2) Экспорт
	Если Значение1 < Значение2 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = ""+Значение1+" >= "+Значение2+", а хотели, чтоб было меньше.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура ПроверитьБольшеИлиРавно(Значение1, Значение2) Экспорт
	Если Значение1 >= Значение2 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = ""+Значение1+" меньше "+Значение2+", а хотели, чтоб было больше или равно.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура ПроверитьМеньшеИлиРавно(Значение1, Значение2) Экспорт
	Если Значение1 <= Значение2 Тогда Возврат; КонецЕсли;
	СтрокаИсключения = ""+Значение1+" больше "+Значение2+", а хотели, чтоб было меньше или равно.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

// в сравниваемой таблице количество строк или больше, или равно количеству строк в исходной таблице,
//
Процедура ПроверитьРавенствоТаблиц(ИсходнаяТаблица, СравниваемаяТаблица, ИндексноеВыражение1, ИндексноеВыражение2) Экспорт
    ИмяКлюча = "ПроверитьТаблицы_Ключ";

	Если СравниваемаяТаблица.КоличествоСтрок() < ИсходнаяТаблица.КоличествоСтрок() Тогда
		СтрокаИсключения = "В сравниваемой таблице меньше строк, чем в исходной, а хотели, чтоб было больше или равно.";
		Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
	КонецЕсли;

	СравниваемаяТаблица.КоличествоСтрок(ИсходнаяТаблица.КоличествоСтрок()); // сначала обрежу таблицу

	ТабРазности = СоздатьОбъект("ИндексированнаяТаблица");
	ТабРазности.Загрузить(ИсходнаяТаблица);
	ТабРазности.ДобавитьИндекс(ИмяКлюча, ИндексноеВыражение1);

	ТабРазности2 = СоздатьОбъект("ИндексированнаяТаблица");
	ТабРазности2.Загрузить(СравниваемаяТаблица);
	ТабРазности2.ДобавитьИндекс(ИмяКлюча, ИндексноеВыражение2);

	ТабРазности.Разность(ТабРазности2, ИмяКлюча, ИмяКлюча);

	Если ТабРазности.КоличествоСтрок() = 0 Тогда Возврат; КонецЕсли;
	
	СтрокаИсключения = "Найдены различия между исходной и сравниваемой таблицами, а хотели, чтоб было они были равны.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);
КонецПроцедуры

Процедура ПроверитьПустоеЗначение(Значение) Экспорт
	Assert(Значение);
КонецПроцедуры

Процедура ПроверитьНеПустоеЗначение(Значение) Экспорт
	AssertNot(Значение);
КонецПроцедуры

Функция МодульВызоваМетода(Объект, ИмяМетода, ЧислоПараметров)
	ТекстМодуля = "";
	Для ъ=1 По ЧислоПараметров  Цикл
		ТекстМодуля = ТекстМодуля + "Перем Параметр"+ъ+" Экспорт;"+РазделительСтрок;
	КонецЦикла;
	
	ТекстМодуля = ТекстМодуля + "
	|Процедура Добавить(Номер, Параметр) Экспорт
	|";
	
	Для ъ=1 По ЧислоПараметров Цикл
		ТекстМодуля = ТекстМодуля + "Если Номер = "+ ъ +" Тогда Параметр"+ъ+" = Параметр; КонецЕсли;"+РазделительСтрок;
	КонецЦикла;
	
	ТекстМодуля = ТекстМодуля +
	"КонецПроцедуры
	|";
	
	стрПараметры = "";
	Для ъ=1 По ЧислоПараметров Цикл
		стрПараметры = стрСоединить(стрПараметры, "Параметр"+ъ);
	КонецЦикла;
	
	ТекстМодуля = ТекстМодуля + "
	|Функция Вызвать(Объект, ОбъектИсключения) Экспорт
	|	//Сообщить(Параметр1);
	|	Попытка
	|		" + ?(ПустоеЗначение(Объект)=0, "Объект.", "") + ИмяМетода+"(" + стрПараметры + ");
	|		Возврат 0;
	|	Исключение 
	|	КонецПопытки;
	|
	|	ВМ = СоздатьОбъект(""ВыполняемыйМодуль"");
	|	ОбъектИсключения = ВМ.ПолучитьИсключение();
	|	Возврат 1; 
	|КонецФункции
	|";
	//ТекстМодуля = ТекстМодуля + "
	//|Процедура Вызвать(Объект) Экспорт
	//|		" + ?(ПустоеЗначение(Объект)=0, "Объект.", "") + ИмяМетода+"(" + стрПараметры + ");
	//|КонецПроцедуры
	//|";
	
	ВМ = СоздатьОбъект("ВыполняемыйМодуль");
	ВМ.УстановитьМодуль(ТекстМодуля);
	Возврат ВМ;
КонецФункции

// проверить исключение для методов с неопределенным числом параметров !!
// Объект может быть пустым значением, тогда это просто вызов глобального метода
// Например, таким образом удобно тестировать метод СоздатьОбъект("");
//
Процедура ПроверитьИсключение(Объект, ИмяМетода) Экспорт
	
	спПараметры = Сам().ПолучитьСписокПараметров("ПроверитьИсключение");
	ЧислоПараметров = спПараметры.РазмерСписка();

	ВМ = МодульВызоваМетода(Объект, ИмяМетода, ЧислоПараметров);

	Упал=0;
	Попытка                   
		фРез = ВМ.КомпилироватьМодуль();
		фРез = ВМ.ВыполнитьМодуль();
		
		Для ъ=1 По ЧислоПараметров Цикл
			ВМ.Добавить(ъ, спПараметры.ПолучитьЗначение(ъ));
		КонецЦикла;
		
		ОбъектИсключения = "";
		фБылоИсключение = ВМ.Вызвать(Объект, ОбъектИсключения);
		               
		Если фБылоИсключение = 1 Тогда
			Упал = 1;
		КонецЕсли;
		//ВМ.Вызвать(Объект);
	Исключение
		Упал=1;
	КонецПопытки;

	Если Упал=1 Тогда Возврат; КонецЕсли;
	
	СтрокаИсключения = "Хотели исключения, а его не было.";
	Сам().ВыброситьИскл(СтрокаИсключения, СтрокаИсключения);

КонецПроцедуры

Функция _ПолучитьКод() Экспорт
	Предупреждение("Вызвана _ПолучитьКод");
	Возврат Описание();
КонецФункции
