[SOURCE-CODE] Repositorio de tests de unidad y tests de integración para .NET

Iniciado por Eleкtro, 16 Diciembre 2016, 02:20 AM

0 Miembros y 1 Visitante están viendo este tema.

Eleкtro




¡Buenas!

Me pareció original la idea de publicar este tema para que podamos compartir tests de unidad (Unit Test) y/o tests de integración (Integration Test) que sean reutilizables,
como una especie de snippets de código. Y así mentener nuestros proyectos libres de bugs.




Test de Evaluación del Tamaño de Estructuras

El siguiente test, sirve para evaluar el tamaño de la instancia de las estructuras definidas en un ensamblado.

El test fallará en caso de que el tamaño de "X" instancia sea menor que el mínimo recomendado (8 bytes) o mayor que el máximo recomendado (16 bytes) según las directrices de diseño de Microsoft .NET.

Este ejemplo, lejos de ilustrar como se debe escribir un test siguiendo buenas prácticas para evaluar cada estructura por individual, lo he diseñado de tal forma que se pueda automatizar a gran escala,
es un código reutilizable que se puede adaptar con el menor esfuerzo solo haciendo un copy&paste; para ello he recurrido a Reflection, de esta manera podemos cargar los
ensamblados referenciados que especifiquemos en un Array de tipo String(), y obtener y evaluar todas las estructuras visibles de dichos ensamblados.

Configuración Del Test:

Esta class nos servirá para mantener una referencia de los (nombres de) ensamblados que se evaluarán en el test.
Como es evidente, los ensamblados deberán estar referenciados en el proyecto de Unit Testing:


Código (vbnet) [Seleccionar]
Public NotInheritable Class Fields

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' The referenced assembly names to test their members.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Public Shared ReadOnly AssemblyNames As String() = {
       "Microsoft.VisualStudio.QualityTools.UnitTestFramework",
       "..."
   }

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' The minimum recommended size for a Structure type.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <remarks>
   ''' <see href="http://stackoverflow.com/a/1082340/1248295"/>
   ''' </remarks>
   ''' ----------------------------------------------------------------------------------------------------
   Public Shared ReadOnly MinimumRecommendedStructureSize As Integer = 8

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' The maximum recommended size for a Structure type.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <remarks>
   ''' <see href="http://msdn.microsoft.com/en-us/library/ms229017.aspx"/>
   ''' </remarks>
   ''' ----------------------------------------------------------------------------------------------------
   Public Shared ReadOnly MaximumRecommendedStructureSize As Integer = 16

   Private Sub New()
   End Sub

End Class


El Test:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 15-December-2016
' ***********************************************************************

Option Strict On
Option Explicit On
Option Infer Off

Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports System.Reflection
Imports System.Runtime.InteropServices

''' <summary>
''' Performs various tests on the <see langword="Structure"/> members of all the assemblies defined in
''' <see cref="Fields.AssemblyNames"/>.
''' </summary>
<TestClass()>
Public Class StructureTests

#Region " Test Methods "

   ''' <summary>
   ''' Performs a test on the <see langword="Structure"/> members of all the assemblies defined in
   ''' <see cref="Fields.AssemblyNames"/>,
   ''' to determine whether a structure has the proper instance size regarding to .NET design guidelines.
   ''' </summary>
   <TestMethod()>
   <TestCategory("Structures")>
   Public Sub TestStructureSizes()

       Dim testFailed As Boolean = False
       Dim testException As AssertFailedException = Nothing

       ' Safe Structures to exclude in this test.
       ' ----------------------------------------
       ' These structures could be smaller or bigger than what is recommended, however, are not considered an error.
       Dim excludedStructs As String() = {
           "MyNamespace.MyStructure"
       }

       For Each assName As String In Fields.AssemblyNames

           Dim ass As Assembly = Assembly.Load(assName)
           Debug.WriteLine(String.Format("Testing Assembly '{0}.dll'...", assName))
           Debug.WriteLine(String.Empty)

           Dim excludedStructures As IEnumerable(Of Type) =
               From t As Type In ass.GetTypes()
               Where (t.IsValueType) AndAlso (Not t.IsClass) AndAlso (Not t.IsEnum) AndAlso (t.IsVisible)
               Where excludedStructs.Contains(String.Format("{0}.{1}", t.Namespace, t.Name))
               Order By String.Format("{0}.{1}", t.Namespace, t.Name)

           Dim includedStructures As IEnumerable(Of Type) =
               From t As Type In ass.GetTypes()
               Where (t.IsValueType) AndAlso (Not t.IsClass) AndAlso (Not t.IsEnum) AndAlso (t.IsVisible)
               Where Not excludedStructs.Contains(String.Format("{0}.{1}", t.Namespace, t.Name))
               Order By String.Format("{0}.{1}", t.Namespace, t.Name)

           If (excludedStructures.Count <> 0) Then
               Debug.WriteLine(String.Format("    Excluded Structures:"))
               For Each t As Type In excludedStructures
                   Debug.WriteLine(String.Format("        '{0}.{1}')",
                                             t.Namespace, t.Name))
               Next t
               Debug.WriteLine(String.Empty)
           End If

           If (includedStructures.Count <> 0) Then
               For Each t As Type In includedStructures
                   Try
                       Me.EvaluateStructureSize(t)

                   Catch ex As AssertFailedException
                       Debug.WriteLine(String.Format("    Testing Structure '{0}.{1}' ({2} Bytes)... FAIL", t.Namespace, t.Name, Marshal.SizeOf(t)))
                       If (testException Is Nothing) Then
                           testException = ex
                           testFailed = True
                       End If

                   Catch ex As Exception
                       Debug.WriteLine(String.Format("    Testing Structure '{0}.{1}'... ERROR. EXCEPTION THROWN.",
                                                     t.Namespace, t.Name))
                       Debug.WriteLine("EXCEPTION MESSAGE:")
                       Debug.WriteLine(ex.Message)
                       Throw

                   End Try

               Next t
               Debug.WriteLine(String.Empty)
           End If

           If (testFailed) Then
               Throw testException
           End If

       Next assName

   End Sub

#End Region

#Region " Private Methods "

   ''' <summary>
   ''' Determines whether the instance size of a structure is smaller and/or greater than the size recommended.
   ''' </summary>
   Private Sub EvaluateStructureSize(ByVal t As Type)

       Dim currentStructureSize As Integer = Marshal.SizeOf(t)

       Assert.IsTrue((currentStructureSize >= Fields.MinimumRecommendedStructureSize),
                       String.Format("The current instance size of Structure '{0}.{1}' is {2} bytes, which is smaller than the minimum recommended {3} bytes.",
                                     t.Namespace, t.Name, currentStructureSize, Fields.MinimumRecommendedStructureSize))

       Assert.IsTrue((currentStructureSize <= Fields.MaximumRecommendedStructureSize),
                       String.Format("The current instance size of Structure '{0}.{1}' is {2} bytes, which is greater than the maximum recommended {3} bytes.",
                                     t.Namespace, t.Name, currentStructureSize, Fields.MaximumRecommendedStructureSize))

       Debug.WriteLine(String.Format("    Testing Structure '{0}.{1}' ({2} Bytes)... Ok", t.Namespace, t.Name, currentStructureSize))

   End Sub

#End Region

End Class



Resultado de Test Satisfactorio:

CitarTest Name:  TestStructureSizes
Test Outcome:   Passed
Result StandardOutput:  
Debug Trace:

Testing Assembly 'Elektro.Application.dll'...

   Testing Structure 'Elektro.Application.UI.Types.NonClientAreaMargins' (16 Bytes)... Ok

Testing Assembly 'Elektro.Application.ThirdParty.dll'...

Testing Assembly 'Elektro.Core.dll'...

   Testing Structure 'Elektro.Core.Text.RegEx.Types.MatchPositionInfo' (16 Bytes)... Ok

Testing Assembly 'Elektro.Imaging.dll'...

Testing Assembly 'Elektro.Interop.dll'...

   Excluded Structures:
       'Elektro.Interop.Win32.Types.AppbarData')
       'Elektro.Interop.Win32.Types.BlendFunction')
       'Elektro.Interop.Win32.Types.CallWndProcStruct')
       ...

Testing Assembly 'Elektro.Multimedia.dll'...

   Testing Structure 'Elektro.Multimedia.Types.StereoVolume' (8 Bytes)... Ok

Testing Assembly 'Elektro.Net.dll'...

Testing Assembly 'Elektro.Processes.dll'...

Testing Assembly 'Elektro.System.dll'...



Reporte de Test Fallido:









Eleкtro

Test Para Descubrir Valores Duplicados en Enums

El siguiente test, sirve para determinar si alguna de las Enums definidas en un ensamblado contiene valores duplicados (e indeseados), y qué valores son esos.

El test fallará en caso de que "X" Enum contenga al menos 1 valor duplicado. Se pueden excluir enumeraciones en el test.

Este ejemplo lo he diseñado de tal forma que se pueda automatizar a gran escala, es un código reutilizable que se puede adaptar con el menor esfuerzo solo haciendo un copy&paste;
para ello he recurrido a Reflection, de esta manera podemos cargar los ensamblados referenciados que especifiquemos en un Array de tipo String(),
y obtener y evaluar todas las enumeraciones visibles de dichos ensamblados.

Ejemplo de una Enum con valores duplicados:

Código (vbnet) [Seleccionar]
Public Enum MyEnum As Integer
   Name1 = 0
   Name2 = 1
   Name3 = 1
   Name4 = MyEnum.Name1
End Enum


Configuración Del Test:

Esta class nos servirá para mantener una referencia de los (nombres de) ensamblados que se evaluarán en el test.
Como es evidente, los ensamblados deberán estar referenciados en el proyecto de Unit Testing:


Código (vbnet) [Seleccionar]
Public NotInheritable Class Fields

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' The referenced assembly names to test their members.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Public Shared ReadOnly AssemblyNames As String() = {
       "Microsoft.VisualStudio.QualityTools.UnitTestFramework",
       "..."
   }

   Private Sub New()
   End Sub

End Class



El Test:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 15-December-2016
' ***********************************************************************

Option Strict On
Option Explicit On
Option Infer Off

Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports System.Reflection

''' <summary>
''' Performs various tests on the <see cref="[Enum]"/> members of all the assemblies defined in
''' <see cref="Fields.AssemblyNames"/>.
''' </summary>
<TestClass()>
Public Class EnumTests

#Region " Test Methods "

   ''' <summary>
   ''' Performs a test on the <see cref="[Enum]"/> members of all the assemblies defined in
   ''' <see cref="Fields.AssemblyNames"/>,
   ''' to determine whether a <see cref="[Enum]"/> contains duplicated values.
   ''' </summary>
   <TestMethod()>
   <TestCategory("Enums")>
   Public Sub TestEnumDuplicatedValues()

       Dim testFailed As Boolean = False
       Dim testException As AssertFailedException = Nothing

       ' Safe Enums to exclude in this test.
       ' -----------------------------------
       ' These enums could contain duplicated values, however, are not considered a bug,
       ' they are defined like that for design purposes.
       Dim excludedEnums As String() = {
           "MyNamespace.MyEnum"
       }

       For Each assName As String In Fields.AssemblyNames

           Dim ass As Assembly = Assembly.Load(assName)
           Debug.WriteLine(String.Format("Testing Assembly '{0}.dll'...", assName))
           Debug.WriteLine(String.Empty)

           Dim excludedTypes As IEnumerable(Of Type) =
               From t As Type In ass.GetLoadableTypes()
               Where t.IsEnum
               Where excludedEnums.Contains(String.Format("{0}.{1}", t.Namespace, t.Name))
               Order By String.Format("{0}.{1}", t.Namespace, t.Name)

           Dim includedTypes As IEnumerable(Of Type) =
               From t As Type In ass.GetLoadableTypes()
               Where t.IsEnum
               Where Not excludedEnums.Contains(String.Format("{0}.{1}", t.Namespace, t.Name))
               Order By String.Format("{0}.{1}", t.Namespace, t.Name)

           If (excludedTypes.Count <> 0) Then
               Debug.WriteLine(String.Format("    Excluded Enums:"))
               For Each t As Type In excludedTypes
                   Debug.WriteLine(String.Format("        '{0}.{1}' ({2})",
                                                 t.Namespace, t.Name, Type.GetTypeCode(t).ToString))
               Next t
               Debug.WriteLine(String.Empty)
           End If

           If (includedTypes.Count <> 0) Then
               For Each t As Type In includedTypes
                   Try
                       Me.EvaluateEnumDuplicatedValues(t)

                   Catch ex As NotSupportedException
                       Debug.WriteLine(String.Format("    Testing Enum '{0}.{1}' As {2}... IGNORED. NOT SUPPORTED.",
                                                     t.Namespace, t.Name, Type.GetTypeCode(t).ToString()))

                   Catch ex As AssertFailedException
                       Debug.WriteLine(String.Format("    Testing Enum '{0}.{1}' As {2} ({3} values)... TEST FAIL.",
                                                     t.Namespace, t.Name, Type.GetTypeCode(t).ToString(), [Enum].GetValues(t).Length))

                       If (testException Is Nothing) Then
                           testException = ex
                           testFailed = True
                       End If

                   Catch ex As Exception
                       Debug.WriteLine(String.Format("    Testing Enum '{0}.{1}' As {2}... ERROR. EXCEPTION THROWN.",
                                                     t.Namespace, t.Name, Type.GetTypeCode(t).ToString()))
                       Debug.WriteLine("EXCEPTION MESSAGE:")
                       Debug.WriteLine(ex.Message)
                       Throw

                   End Try
               Next t
               Debug.WriteLine(String.Empty)
           End If

           If (testFailed) Then
               Throw testException
           End If

       Next assName

   End Sub

#End Region

#Region " Private Methods "

   ''' <summary>
   ''' Determines whether the definition of the source <see cref="[Enum]"/> contains duplicated values.
   ''' </summary>
   Private Sub EvaluateEnumDuplicatedValues(ByVal t As Type)

       Dim values As Array = [Enum].GetValues(t)
       Dim valueCount As Integer = values.Length

       Dim repeatedValueNames As Object() =
           (values.Cast(Of Object).GroupBy(Function(value As Object) value).
                                   Where(Function(group As IGrouping(Of Object, Object)) group.Count > 1).
                                   Select(Function(group As IGrouping(Of Object, Object)) group.Key)).ToArray()

       Dim repeatedValues As Long() = repeatedValueNames.Select(Function(x As Object) Convert.ToInt64(x)).ToArray()
       Dim repeatedValueCount As Integer = repeatedValueNames.Count

       Dim formattedValues As New List(Of String)
       For i As Integer = 0 To (repeatedValueNames.Length - 1)
           formattedValues.Add(String.Format("{0}={1} (&H{2})",
                                             repeatedValueNames(i), repeatedValues(i),
                                             repeatedValues(i).ToString("X").TrimStart("F"c)))
       Next

       Assert.AreEqual(0, repeatedValueCount,
                       String.Format("Enum '{0}.{1}' has defined these duplicated values: {2}",
                                     t.Namespace, t.Name, Environment.NewLine &
                                     String.Join(Environment.NewLine, formattedValues)))

       Debug.WriteLine(String.Format("    Testing Enum '{0}.{1}' As {2} ({3} values)... Ok.",
                                     t.Namespace, t.Name, Type.GetTypeCode(t).ToString(), valueCount))

   End Sub

#End Region

End Class



Resultado de Test Satisfactorio:

CitarTest Name:  TestEnumDuplicatedValues
Test Outcome:   Passed
Result StandardOutput:  
Debug Trace:

Testing Assembly 'Elektro.Application.dll'...

   Testing Enum 'Elektro.Application.Data.Enums.SerializationType' As Int32 (3 values)... Ok
   Testing Enum 'Elektro.Application.Enums.ComparerResult' As Int32 (3 values)... Ok
   Testing Enum 'Elektro.Application.Enums.ProcessArchitecture' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.ControlHintType' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.FadingEffect' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.ListBoxItemSelectionState' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.RowMoveDirection' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.ScreenDockingPosition' As Int32 (9 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.SortModifiers' As Int32 (3 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoCheckBoxEvents' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoComboBoxEvents' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoCommand' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoDateTimePickerEvents' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoListBoxEvents' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoListViewEvents' As Int32 (3 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoMaskedTextBoxEvents' As Int32 (5 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoMonthCalendarEvents' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoNumericUpDownEvents' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoRichTextBoxEvents' As Int32 (5 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoTextBoxEvents' As Int32 (5 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.UndoRedoTextUpdateBehavior' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.WindowAnimation' As Int32 (20 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.WindowDockingPosition' As Int32 (12 values)... Ok
   Testing Enum 'Elektro.Application.UI.Enums.WindowEdges' As Int32 (9 values)... Ok

Testing Assembly 'Elektro.Core.dll'...

   Excluded Enums:
       'Elektro.Core.IO.Enums.DriveFileSystem' (Int32)
       'Elektro.Core.Maths.Types.Position' (Int32)

   Testing Enum 'Elektro.Core.Cryptography.Enums.HexadecimalStyle' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Core.DateAndTime.Enums.TimeMeasurerState' As Int32 (3 values)... Ok
   Testing Enum 'Elektro.Core.DateAndTime.Enums.TimeUnit' As Int32 (5 values)... Ok
   Testing Enum 'Elektro.Core.Generics.Enums.EnumFindDirection' As Int32 (5 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.DateAttribute' As Int32 (4 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.DeviceEvent' As Int32 (3 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.DiscType' As Int64 (7 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.DriveFormatResult' As Int32 (19 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.HotkeyModifiers' As Int16 (6 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.KeyBehavior' As Int32 (3 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.MouseButton' As Int32 (9 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.MouseWheelDirection' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.ShortcutHotkeyModifier' As Int16 (5 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.ShortcutWindowState' As Int32 (4 values)... Ok
   Testing Enum 'Elektro.Core.IO.Enums.SizeUnits' As Int64 (7 values)... Ok
   Testing Enum 'Elektro.Core.IO.Types.DeviceType' As Int32 (1 values)... Ok
   Testing Enum 'Elektro.Core.Maths.Enums.MetaCollectionType' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Core.Text.Enums.StringCase' As Int32 (13 values)... Ok
   Testing Enum 'Elektro.Core.Text.Enums.StringDirection' As Int32 (2 values)... Ok
   Testing Enum 'Elektro.Core.Text.Enums.TextDirection' As Int32 (2 values)... Ok

...


Reporte de Test Fallido:









UPDATE

Se me olvidó incluir la función GetLoadabletypes. Aquí la tienen:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 18-December-2016
' ***********************************************************************

#Region " Public Members Summary "

#Region " Functions "

' Assembly.GetLoadableTypes() As Type()

#End Region

#End Region

#Region " Option Statements "

Option Strict On
Option Explicit On
Option Infer Off

#End Region

#Region " Imports "

Imports System.ComponentModel
Imports System.Reflection
Imports System.Runtime.CompilerServices

#End Region

#Region " Assembly Extensions "

Namespace Extensions.[Assembly]

    ''' ----------------------------------------------------------------------------------------------------
    ''' <summary>
    ''' Contains custom extension methods to use with the <see cref="Global.System.Reflection.Assembly"/> type.
    ''' </summary>
    ''' ----------------------------------------------------------------------------------------------------
    <HideModuleName>
    Public Module Types

#Region " Public Extension Methods "

        ''' ----------------------------------------------------------------------------------------------------
        ''' <summary>
        ''' Gets the types defined in the specified a <see cref="Global.System.Reflection.Assembly"/>,
        ''' only the types that can be loaded.
        ''' <para></para>
        ''' The types that cannot be loaded (eg. due to a missing 3rd party assembly reference) are not returned.
        ''' </summary>
        ''' ----------------------------------------------------------------------------------------------------
        ''' <param name="sender">
        ''' The source <see cref="Global.System.Reflection.Assembly"/>.
        ''' </param>
        ''' ----------------------------------------------------------------------------------------------------
        ''' <returns>
        ''' An array that contains all the types that are defined in this assembly, only the types that can be loaded.
        ''' <para></para>
        ''' The types that cannot be loaded (eg. Due to a missing 3rd party assembly reference) are not returned.
        ''' </returns>
        ''' ----------------------------------------------------------------------------------------------------
        <DebuggerStepThrough>
        <Extension>
        <EditorBrowsable(EditorBrowsableState.Always)>
        Public Function GetLoadableTypes(ByVal sender As Global.System.Reflection.Assembly) As Global.System.Type()

            Try
                Return sender.GetTypes()

            Catch e As ReflectionTypeLoadException
                Return (From t As Global.System.Type In e.Types
                        Where (t IsNot Nothing) AndAlso (t.TypeInitializer IsNot Nothing)
                        ).ToArray()

            End Try

        End Function

#End Region

    End Module

End Namespace

#End Region








Eleкtro

Test Para Descubrir Errores en Types IDisposable

El siguiente test, sirve para determinar si alguno de los types definidos en un ensamblado (los types que implementen la interfáz IDisposable) lanza alguna excepción  durante el proceso de instanciación y liberación.
El type debe tener un constructor sin parámetros para poder ser evaluado.

El test fallará en caso de que "X" type lance una excepción al momento de instanciarse o al momento de llamar al método Dispose para liberar sus recursos administrados y/o no administrados.

Este ejemplo lo he diseñado de tal forma que se pueda automatizar a gran escala, es un código reutilizable que se puede adaptar con el menor esfuerzo solo haciendo un copy&paste;
para ello he recurrido a Reflection, de esta manera podemos cargar los ensamblados referenciados que especifiquemos en un Array de tipo String(),
y obtener y evaluar todos los types visibles de dichos ensamblados.

Configuración Del Test:

Esta class nos servirá para mantener una referencia de los (nombres de) ensamblados que se evaluarán en el test.
Como es evidente, los ensamblados deberán estar referenciados en el proyecto de Unit Testing:


Código (vbnet) [Seleccionar]
Public NotInheritable Class Fields

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' The referenced assembly names to test their members.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Public Shared ReadOnly AssemblyNames As String() = {
       "Microsoft.VisualStudio.QualityTools.UnitTestFramework",
       "..."
   }

   Private Sub New()
   End Sub

End Class



El Test:

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 16-December-2016
' ***********************************************************************

Option Strict On
Option Explicit On
Option Infer Off

Imports Microsoft.VisualStudio.TestTools.UnitTesting
Imports System.Reflection
Imports System.IO

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Tests for the <see cref="IDisposable"/> members defined in the assemblies of <see cref="Fields.AssemblyNames"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
<TestClass()>
Public NotInheritable Class TypeTests

#Region " Test Methods "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Performs a test on the <see cref="IDisposable"/> members defined in the assemblies of <see cref="Fields.AssemblyNames"/>,
   ''' to evaluate the disposability of the <see cref="IDisposable"/> members.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <TestMethod()>
   <TestCategory("Types")>
   Public Sub TestIDisposableTypes()

       Dim testFailed As Boolean = False
       Dim testException As AssertFailedException = Nothing

       ' Safe disposable types to exclude in this test.
       ' -----------------------------------
       ' These disposable types could throw an exception when disposed, however, are not considered a bug.
       Dim excludedTypeNames As String() = {
       }

       For Each assName As String In Fields.AssemblyNames

           Dim ass As Assembly = Assembly.Load(assName)
           Debug.WriteLine(String.Format("Testing Assembly '{0}.dll'...", assName))
           Debug.WriteLine(String.Empty)

           Dim excludedTypes As IEnumerable(Of Type) =
               From t As Type In ass.GetTypes()
               Where (t.GetInterfaces.Contains(GetType(IDisposable))) AndAlso (t.IsVisible)
               Where excludedTypeNames.Contains(String.Format("{0}.{1}", t.Namespace, t.Name))
               Order By String.Format("{0}.{1}", t.Namespace, t.Name)

           Dim includedTypes As IEnumerable(Of Type) =
               From t As Type In ass.GetTypes()
               Where (t.GetInterfaces.Contains(GetType(IDisposable))) AndAlso (t.IsVisible)
               Where Not excludedTypeNames.Contains(String.Format("{0}.{1}", t.Namespace, t.Name))
               Order By String.Format("{0}.{1}", t.Namespace, t.Name)

           If (excludedTypes.Count <> 0) Then
               Debug.WriteLine(String.Format("    Excluded Disposable Types:"))
               For Each t As Type In excludedTypes
                   Debug.WriteLine(String.Format("        '{0}.{1}')", t.Namespace, t.Name))
               Next t
               Debug.WriteLine(String.Empty)
           End If

           If (includedTypes.Count <> 0) Then
               For Each t As Type In includedTypes
                   Try
                       Me.EvaluateDisposableType(t)

                   Catch ex As TargetInvocationException When (TypeOf ex.InnerException Is FileNotFoundException)
                       Debug.WriteLine(String.Format("    Testing Disposable Type '{0}.{1}'... IGNORED. MISSING ASSEMBLY REFERENCE.", t.Namespace, t.Name))

                   Catch ex As FileNotFoundException
                       Debug.WriteLine(String.Format("    Testing Disposable Type '{0}.{1}'... IGNORED. MISSING ASSEMBLY REFERENCE.", t.Namespace, t.Name))

                   Catch ex As MissingMethodException
                       Debug.WriteLine(String.Format("    Testing Disposable Type '{0}.{1}'... IGNORED. NO PARAMETERLESS CONSTRUCTOR.", t.Namespace, t.Name))

                   Catch ex As ArgumentException
                       Debug.WriteLine(String.Format("    Testing Disposable Type '{0}.{1}'... IGNORED. GENERIC PARAMETER REQUIRED.", t.Namespace, t.Name))

                   Catch ex As Exception
                       Debug.WriteLine(String.Format("    Testing Disposable Type '{0}.{1}'... ERROR. EXCEPTION THROWN.", t.Namespace, t.Name))
                       Debug.WriteLine("EXCEPTION MESSAGE:")
                       Debug.WriteLine(ex.Message)
                       Throw

                   End Try
               Next t
               Debug.WriteLine(String.Empty)
           End If

           If (testFailed) Then
               Throw testException
           End If

       Next assName

   End Sub

#End Region

#Region " Private Methods "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Evaluates whether a disposable type throws an exception during instantiation and/or disposal operation.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="t">
   ''' The source type.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   Private Sub EvaluateDisposableType(ByVal t As Type)

       Dim instance As IDisposable = DirectCast(Activator.CreateInstance(t), IDisposable)
       instance.Dispose()
       instance = Nothing

       Debug.WriteLine(String.Format("    Testing Disposable Type '{0}.{1}'... Ok", t.Namespace, t.Name))

   End Sub

#End Region

End Class



Resultado de Test Satisfactorio:

CitarTest Name:  TestIDisposableTypes
Test Outcome:   Passed
Result StandardOutput:  
Debug Trace:

Testing Assembly 'Elektro.Application.dll'...

   Testing Disposable Type 'Elektro.Application.UI.Types.ControlDragger'... Ok
   Testing Disposable Type 'Elektro.Application.UI.Types.EditControlHook'... Ok
   Testing Disposable Type 'Elektro.Application.UI.Types.FormDragger'... Ok
   Testing Disposable Type 'Elektro.Application.UI.Types.UndoRedo`1'... IGNORED. GENERIC PARAMETER REQUIRED.

Testing Assembly 'Elektro.Imaging.dll'...

   Testing Disposable Type 'Elektro.Imaging.Types.ScreenRegionSelector'... Ok

Testing Assembly 'Elektro.Interop.dll'...

   Testing Disposable Type 'Elektro.Interop.Types.Compiler'... Ok
   Testing Disposable Type 'Elektro.Interop.Types.CompilerSettings'... Ok
   Testing Disposable Type 'Elektro.Interop.Types.CSharpCompiler'... IGNORED. NO PARAMETERLESS CONSTRUCTOR.
   Testing Disposable Type 'Elektro.Interop.Types.SafeBitmapHandle'... Ok
   Testing Disposable Type 'Elektro.Interop.Types.SafeCursorHandle'... Ok
   Testing Disposable Type 'Elektro.Interop.Types.SafeIconHandle'... Ok
   Testing Disposable Type 'Elektro.Interop.Types.SafeRegionHandle'... Ok
   Testing Disposable Type 'Elektro.Interop.Types.SafeWindowHandle'... Ok
   Testing Disposable Type 'Elektro.Interop.Types.VisualBasicCompiler'... IGNORED. NO PARAMETERLESS CONSTRUCTOR.
   Testing Disposable Type 'Elektro.Interop.Types.ZeroInvalidHandle'... IGNORED. NO PARAMETERLESS CONSTRUCTOR.

Testing Assembly 'Elektro.Multimedia.dll'...

   Testing Disposable Type 'Elektro.Multimedia.Types.AudioPlayer'... Ok
   Testing Disposable Type 'Elektro.Multimedia.Types.WaveRecorder'... Ok

Testing Assembly 'Elektro.Net.dll'...

   Testing Disposable Type 'Elektro.Net.Types.NetworkTrafficMonitor'... IGNORED. NO PARAMETERLESS CONSTRUCTOR.
   Testing Disposable Type 'Elektro.Net.Types.ProcessTrafficMonitor'... IGNORED. NO PARAMETERLESS CONSTRUCTOR.

Testing Assembly 'Elektro.Processes.dll'...

   Testing Disposable Type 'Elektro.Processes.Types.ProcessMonitor'... Ok
   Testing Disposable Type 'Elektro.Processes.Types.ProcessWatcher'... Ok

Testing Assembly 'Elektro.System.dll'...

   Testing Disposable Type 'Elektro.System.Types.PowerStateMonitor'... Ok


Reporte de Test Fallido:



CitarTesting Assembly 'Elektro.Processes.dll'...

   Testing Disposable Type 'Elektro.Processes.Types.ProcessMonitor'... ERROR. EXCEPTION THROWN.
   EXCEPTION MESSAGE:
   Monitor is already stopped.