나는 테스트의 방법이 거의없고 많은 양의 코드가 최근에 변경된 프로젝트에 참여하고 있습니다. 특히 코드가 하나의 데이터 공급자를 사용하여 다른 곳으로 이동하고 DataSet이 DTO로 대체되었습니다.IL에서 C# 로의 변환
나는 이것을 가능한 한 많이 테스트하려고하지만, 필요한 시간 내에 수많은 사람들이 한 모든 변경 사항에 대한 테스트를 현실적으로 만들 수는 없습니다.
Mono.cecil을 사용하여 모든 데이터베이스 호출과 관련 저장 프로 시저 이름을 찾고 C#에 정의 된 매개 변수를 데이터베이스의 매개 변수와 비교하는 테스트를 작성할 수있었습니다.
모든 매개 변수가 기본값 인 경우에도이 한 걸음 더 나아가 실제로 메서드를 호출하고 싶습니다. 이 방법은 DataReader에 행이 없을 수도 있지만 스키마를 발견하고이를 정적 매퍼 메서드와 비교해 볼 수 있습니다.
예를 들어
GetRows()가 단순 확장 방법이며 GetDivisionFromRecord를 변환하는 방법을 알아낼 수 없습니다 I Unfortunatley이public static Division GetDivisionFromRecord(record)
{
return new Division
{
Id = record.GetValueOrDefault<long?>("id"),
Name = record.GetValueOrDefault<string>("name")
};
}
처럼 조금 보이는 정적 방법이다
var reader = cmd.ExecuteReader();
var Divisions = (from IDataRecord record in reader.GetRows()
select RecordMapper.GetDivisionFromRecord(record)).ToList();
IL은 mapper 클래스의 정적 메서드 이름으로 캐시 된 정적 대리자를 참조합니다. 메소드 이름을 찾을 수 있다면 Cecil을 사용하여 메소드를 가져오고 GetValueOrDefault에 callvirt opcode를 찾아 데이터베이스 별칭 및 유형 모음을 빌드 할 수 있습니다.
IL은 이렇게 보입니다.
IL_0025: callvirt instance class [System.Data]System.Data.IDataReader IOracleHelper::ExecuteReader(class OracleCommandWrapper)
IL_002a: stloc.0
IL_002b: ldloc.0
IL_002c: call class [mscorlib]System.Collections.Generic.IEnumerable`1<class [System.Data]System.Data.IDataRecord> NullSafeExtensions::GetRows(class [System.Data]System.Data.IDataReader)
IL_0031: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Cast<class [System.Data]System.Data.IDataRecord>(class [mscorlib]System.Collections.IEnumerable)
IL_0036: ldsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_003b: brtrue.s IL_0050
IL_003d: ldnull
IL_003e: ldftn class [Services.Common]Division DataDao::'<GetAlDivisions>b__16'(class [System.Data]System.Data.IDataRecord)
IL_0044: newobj instance void class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division>::.ctor(object, native int)
IL_0049: stsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_004e: br.s IL_0050
IL_0050: ldsfld class [System.Core]System.Func`2<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division> DataDao::'CS$<>9__CachedAnonymousMethodDelegate17'
IL_0055: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!1> [System.Core]System.Linq.Enumerable::Select<class [System.Data]System.Data.IDataRecord, class [Services.Common]Division>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>, class [System.Core]System.Func`2<!!0, !!1>)
IL_005a: call class [mscorlib]System.Collections.Generic.List`1<!!0> [System.Core]System.Linq.Enumerable::ToList<class [Services.Common]Division>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>)
저는 세실과 리플렉션을 모두 사용했으며 CachedAnonymousDelegates를 개인 정적 필드로 볼 수 있습니다. 그러나 실제 메서드 호출을 얻는 방법을 알 수 있습니다.
어떻게 생각해도 될까요?
Telerik은 .NET 어셈블리를 디 컴파일하려는 경우 무료 디 컴파일러를 제공합니다. 아마 시간을 절약 할 수있을 것입니다. 리플렉터와 달리 아직 무료입니다. http://www.telerik.com/products/decompiler.aspx (그리고 나는 Telerk와 아무런 관련이 없기 때문에 공개 할 필요가 없습니다.) – David
이것은 이상한 방법입니다. 소스 제어에있는 버전에 대해 diff를 실행하여 테스트해야 할 항목을 찾으십시오. –
이미 디 컴파일러 mono.cecil을 사용하고 있습니다. Reflector/ILSpy 등의 도구를 사용하고 싶지는 않습니다. 그 이후로 전체 테스트 프로세스가 수동으로 진행될 것이고 회귀 테스트에 사용할 수있는 테스트 케이스가 없을 것이고 데이터베이스 릴리스 등을 확인할 수도 있습니다. – hugo