approccio
Si potrebbe ricorrere all'utilizzo di riflessione per invocare i metodi di prova privati: si sarebbe avere un unico metodo di prova NUnit pubblico che loop su tutti i metodi privati nella dell'assemblea invocando quelli con l'attributo di prova. Il lato negativo di questo approccio è che si può vedere un solo metodo di test in errore alla volta (ma forse si potrebbe esaminare qualcosa di creativo come l'uso di test parametrizzati per risolvere questo problema).
Esempio
Program.fsi
namespace MyNs
module Program =
val visibleMethod: int -> int
Program.fs
namespace MyNs
open NUnit.Framework
module Program =
let implMethod1 x y =
x + y
[<Test>]
let testImpleMethod1() =
Assert.AreEqual(implMethod1 1 1, 2)
let implMethod2 x y z =
x + y + z
[<Test>]
let testImpleMethod2() =
Assert.AreEqual(implMethod2 1 1 1, 3)
let implMethod3 x y z r =
x + y + z + r
[<Test>]
let testImpleMethod3() =
Assert.AreEqual(implMethod3 1 1 1 1, -1)
let implMethod4 x y z r s =
x + y + z + r + s
[<Test>]
let testImpleMethod4() =
Assert.AreEqual(implMethod4 1 1 1 1 1, 5)
let visibleMethod x =
implMethod1 x x
+ implMethod2 x x x
+ implMethod3 x x x x
TestProxy.fs (implementazione del nostro "Approach")
module TestProxy
open NUnit.Framework
[<Test>]
let run() =
///we only want static (i.e. let bound functions of a module),
///non-public methods (exclude any public methods, including this method,
///since those will not be skipped by nunit)
let bindingFlags = System.Reflection.BindingFlags.Static ||| System.Reflection.BindingFlags.NonPublic
///returns true if the given obj is of type TestAttribute, the attribute used for marking nunit test methods
let isTestAttr (attr:obj) =
match attr with
| :? NUnit.Framework.TestAttribute -> true
| _ -> false
let assm = System.Reflection.Assembly.GetExecutingAssembly()
let tys = assm.GetTypes()
let mutable count = 0
for ty in tys do
let methods = ty.GetMethods(bindingFlags)
for mi in methods do
let attrs = mi.GetCustomAttributes(false)
if attrs |> Array.exists isTestAttr then
//using stdout w/ flush instead of printf to ensure messages printed to screen in sequence
stdout.Write(sprintf "running test `%s`..." mi.Name)
stdout.Flush()
mi.Invoke(null,null) |> ignore
stdout.WriteLine("passed")
count <- count + 1
stdout.WriteLine(sprintf "All %i tests passed." count)
Esempio di output (tramite TestDriven.NET)
Privacy non abbiamo mai arrivare a testImplMethod4 poiché non sulla testImpleMethod3:
running test `testImpleMethod1`...passed
running test `testImpleMethod2`...passed
running test `testImpleMethod3`...Test 'TestProxy.run' failed: System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> NUnit.Framework.AssertionException : Expected: 4
But was: -1
at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
C:\Users\Stephen\Documents\Visual Studio 2010\Projects\FsOverflow\FsOverflow\TestProxy.fs(29,0): at TestProxy.run()
--AssertionException
C:\Users\Stephen\Documents\Visual Studio 2010\Projects\FsOverflow\FsOverflow\Program.fs(25,0): at MyNs.Program.testImpleMethod3()
0 passed, 1 failed, 4 skipped (see 'Task List'), took 0.41 seconds (NUnit 2.5.10).
Hai provato a usare InternalsVisibleTo? http://devlicio.us/blogs/derik_whittaker/archive/2007/04/09/internalsvisibleto-testing-internal-methods-in-net-2-0.aspx –
Penso che il mio problema sia un po 'diverso. Posso già compilare i test bene. Tuttavia, non posso eseguirli se non li esporto dal modulo. Suppongo che l'attributo sarebbe di aiuto se potessi arrivare a dire che tutti gli interni sono accessibili a NUnit. Ma non ho idea di dove cominciare, e nessuno dei due - sembra - fa Google. Ovviamente potrei usare l'attributo dopo aver spostato i test su un file diverso, ma quello è un male peggiore. Li uso come documentazione eseguibile, quindi hanno davvero bisogno di essere vicini al codice. Molte grazie per la risposta. – user1002059
Se è compilato, dovrebbe essere eseguito. A meno che tu non abbia i test nello stesso assembly del codice reale o qualcosa del genere. –