0

I have a number of test classes in C# (NUnit Test scripts, compiling on Mono).

Instead of compiling all unit tests into one big assembly, as usual, I'd like to compile the individual class files into separate assemblies. To do so, I'd like to do a dependency analysis, so I can generate the separate assemblies automatically.

What I'm looking for is similar to class dependency analyser which exists for Java

sehe
  • 374,641
  • 47
  • 450
  • 633
Milan Raval
  • 1,880
  • 1
  • 16
  • 33
  • 1
    please clarify the question with examples. It is currently unclear whether you want to compile the Mono Unit Tests on windows; you want to 'generate a DLL for each dependency' (? dependencies are usually DLLs already)... – sehe Oct 21 '11 at 10:47
  • You are right, its very difficult to understand this senario. I have already written that I want to build individual class files, that means I dont want one dll for the whole NUnit test project but I want one dll for each test class file of NUnit test project. thanks – Milan Raval Oct 24 '11 at 07:50
  • to be honest, I think it is just the wording. Regardless, I have posted my answer – sehe Oct 24 '11 at 10:32

2 Answers2

0

Assuming you want to run nunit tests on mono, that should work just fine, ( I am happily using NUnit 2.5 and 2.4 on mono 2.10.6 ).

One common mistake is only copying or keeping track of the .dll file containing the tests. Like any program, the test has dependencies, in your case, they will at least be nunit.framework.dll plus the class/assembly you wish to test ( and any of it's dependencies )

If all you want however is to find the assemblies a given dll references (things it needs to run) you can do this quite easily:

using System.Reflection;

void PrintRefs( string dllfile ){
  var asm = Assembly.ReflectionOnlyLoad ( dllfile );

  foreach ( var aname in asm.GetReferencedAssemblies() ){
    Console.WriteLine( aname.Name );
  }
}

Beware, this will only find the names of assemblies the program or library was compiled with, not any that it might dynamically load at runtime.

IanNorton
  • 7,145
  • 2
  • 25
  • 28
0

Have a look at Mono Cecil.

This library has the capability to 'reflect' (not a very good name for it) on the actual assembly image to do analysis. This assumes that you would be willing to compile down to a 'big' assembly in order to run the dependency analysis using Mono.Cecil.

Edit In fact, you might simply use Cecil to copy the 'big' assembly while filtering out parts of it. That way, you'll not have much of the complexity of compiling the separate assemblies; Look at CecilRoundtrip sample for an example of how to roundtrip (read -> manipulate -> save) assemblies in Cecil.

I have previously published quite extensive examples of how to use Mono Cecil for 'advanced' searches (static call tree search, in essence):

The absolute bare minimum that would be most useful to you would probably be:

var types = assemblies
    .SelectMany(assembly => assembly.MainModule.Types.Cast<TypeDefinition>());

var dependencies = types.ToDictionary(
    key => key,
    typedef => new HashSet<string>(typedef.Methods.Cast<MethodDefinition>()
                .Where(method => null != method.Body) // ignore abstracts and generics
                .SelectMany(method => method.Body.Instructions.Cast<Instruction>())
                .Select(instr => instr.Operand)
                .OfType<TypeReference>().Distinct()
          //    .Where(type => !type.Namespace.StartsWith("System"))
                .Select(type => type.Name)));

foreach (var entry in dependencies)
{
     Console.WriteLine("{0}\t{1}", entry.Key.Name, string.Join(", ", entry.Value.ToArray()));
}

Note the commented line optionally filters out things from the framework (System.String, System.Char etc.).

This will list required types per declared type. To list types used, simply tag on the lookup to assembly name:

                .Select(type => type.Module.Assembly.Name.Name)));

Sample output of the first kind (types required):

SegmentSoortKenmerk     SegmentSoortKenmerk
OperatorValue
Koppelpad       Koppelpad, CodeLeidendVolgend
RedenWaarschuwing
RelExceptions
GecontroleerdDocument   GecontroleerdDocument, GecontroleerdDocument[]
OwiExtraKenmerk OwiExtraKenmerk, Gegeven, BackofficeRelatie
Entiteit        Entiteit, SleutelSysteemObject[], EniteitType

Similar query but using the assembly name lookup:

SegmentSoortKenmerk     Lspo.Business
OperatorValue
Koppelpad       Lspo.Business
RedenWaarschuwing
RelExceptions
GecontroleerdDocument   Lspo.Business
OwiExtraKenmerk Lspo.Business
Entiteit        Lspo.Business
Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • added link to [cecil-roundtrip.cs](https://github.com/mono/cecil/tree/master/tools) as additional inspiration – sehe Oct 24 '11 at 10:41