Я уже писал о контрольных точках - http://18delphi.blogspot.ru/2013/04/blog-post_6244.html
Я достаточно широко применяю этот подход.
Я внедряю тестовый код в реальные проектные файлы.
Позволю привести себе пример:
Тут в класс TscriptParser "внедрено" две "контрольных точки". f_ReadLnLog и f_GetCharLog.
Я такие "контрольные точки" обычно делаю "не руками", а на уровне модели, но всё равно - надеюсь, что идея понятна.
При этом получившиеся "эталоны" я обычно кладу в CVS/SVN и контролирую их разницу. На разных тестовых наборах. Про это я напишу чуть позже.
Пример доступен тут - https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/GUITests/Chapter0/
Я достаточно широко применяю этот подход.
Я внедряю тестовый код в реальные проектные файлы.
Позволю привести себе пример:
unit Script.Parser;
interface
uses
Classes,
CoreObject
;
{$IfNDef NoTesting}
{$Define TestParser}
{$EndIf NoTesting}
type
TscriptParser = class(TCoreObject)
private
f_Stream : TStream;
{$IfDef TestParser}
f_GetCharLog : TStream;
// - сразу думаем о тестировании, в этот поток будем выводить
// результат работы функции GetChar
f_ReadLnLog : TStream;
// - сразу думаем о тестировании, в этот поток будем выводить
// результат работы функции ReadLn
{$EndIf TestParser}
f_EOF : Boolean;
f_CurrentLine : String;
protected
procedure Cleanup; override;
function ReadLn: String;
protected
function GetChar(out aChar: AnsiChar): Boolean;
public
constructor Create(const aStream : TStream; const aFileName : String); overload;
constructor Create(const aFileName : String); overload;
function EOF: Boolean;
procedure NextToken;
end;//TscriptParser
implementation
uses
System.SysUtils
;
constructor TscriptParser.Create(const aStream : TStream; const aFileName : String);
begin
inherited Create;
f_EOF := false;
f_Stream := aStream;
{$IfDef TestParser}
f_GetCharLog := TFileStream.Create(aFileName + '.GetChar.log', fmCreate);
f_ReadLnLog := TFileStream.Create(aFileName + '.ReadLn.log', fmCreate);
{$EndIf TestParser}
end;
constructor TscriptParser.Create(const aFileName : String);
var
l_FileName : String;
begin
l_FileName := ExtractFilePath(ParamStr(0)) + '\' + aFileName;
Create(TFileStream.Create(l_FileName, fmOpenRead), l_FileName);
end;
procedure TscriptParser.Cleanup;
begin
FreeAndNil(f_Stream);
{$IfDef TestParser}
FreeAndNil(f_GetCharLog);
FreeAndNil(f_ReadLnLog);
{$EndIf TestParser}
inherited;
end;
function TscriptParser.GetChar(out aChar: AnsiChar): Boolean;
begin
if (f_Stream.Read(aChar, SizeOf(aChar)) = SizeOf(aChar)) then
begin
Result := true;
{$IfDef TestParser}
f_GetCharLog.Write(aChar, SizeOf(aChar));
{$EndIf TestParser}
end
else
Result := false;
end;
function TscriptParser.ReadLn: String;
{$IfDef TestParser}
const
cEOL : AnsiString = #13#10;
var
l_Result : AnsiString;
{$EndIf TestParser}
var
l_Char : AnsiChar;
l_Line : String;
begin
{$IfDef TestParser}
try
{$EndIf TestParser}
l_Line := '';
while GetChar(l_Char) do
begin
if (l_Char = #13) then
begin
if GetChar(l_Char) then
begin
if (l_Char = #10) then
begin
Result := l_Line;
Exit;
end//l_Char = #10
else
Assert(false, 'Что-то пошло не так, после символа 13 нет символа 10');
end//GetChar(l_Char)
else
Assert(false, 'Что-то пошло не так, после символа 13 сразу конец файла');
end;//l_Char = #13
l_Line := l_Line + l_Char;
end;//while GetChar(l_Char)
f_EOF := true;
Result := l_Line;
{$IfDef TestParser}
finally
l_Result := Result;
f_ReadLnLog.Write(@l_Result[1], Length(l_Result));
f_ReadLnLog.Write(@cEOL[1], Length(cEOL));
end;//try..finally
{$EndIf TestParser}
end;
procedure TscriptParser.NextToken;
begin
while(f_CurrentLine = '') do
begin
f_CurrentLine := ReadLn;
if (f_CurrentLine = '') then
if f_EOF then
Exit;
end;//while(f_NextToken = '')
f_CurrentLine := '';
end;
function TscriptParser.EOF: Boolean;
begin
Result := f_EOF;
end;
end.
Тут в класс TscriptParser "внедрено" две "контрольных точки". f_ReadLnLog и f_GetCharLog.
Я такие "контрольные точки" обычно делаю "не руками", а на уровне модели, но всё равно - надеюсь, что идея понятна.
При этом получившиеся "эталоны" я обычно кладу в CVS/SVN и контролирую их разницу. На разных тестовых наборах. Про это я напишу чуть позже.
Пример доступен тут - https://sourceforge.net/p/rumtmarc/code-0/HEAD/tree/trunk/Blogger/GUITests/Chapter0/
Комментариев нет:
Отправить комментарий