Nunit: Pruebas unitarias fallidas en nunit.framework.tests después de un nuevo clon

Creado en 25 jun. 2018  ·  31Comentarios  ·  Fuente: nunit/nunit

Acabo de tomar un nuevo clon de nunit y abrí la solución en Visual Studio 2017 (Comunidad 15.7.4) con el último Adaptador de prueba NUnit 3 (3.10 con Ejecutar pruebas en paralelo) que se ejecuta en Windows 10 Professional y seleccioné "Debug-AnyCPU "y presione construir.

Después de leer el BUILDING.md, parece que debería ignorar cualquier falla que no provenga de nunit.framework.tests- * y nunitlite.tests- *

Sin embargo, fuera de la puerta, obtengo 2 fallas de nunit.framework.tests- *

Primer error:

Test Name:  TestCaseSourceCanAccessWorkDirectory("C:\\Users\\ace.olszowka\\source\\nunit\\bin\\Debug\\net20")
Test FullName:  NUnit.Framework.TestContextTests.TestCaseSourceCanAccessWorkDirectory("C:\\Users\\ace.olszowka\\source\\nunit\\bin\\Debug\\net20")
Test Source:    C:\Users\ace.olszowka\source\nunit\src\NUnitFramework\tests\TestContextTests.cs : line 110
Test Outcome:   Failed
Test Duration:  0:00:00.001

Result StackTrace:  at NUnit.Framework.TestContextTests.TestCaseSourceCanAccessWorkDirectory(String workDirectory) in C:\Users\ace.olszowka\source\nunit\src\NUnitFramework\tests\TestContextTests.cs:line 112
Result Message: 
Expected string length 34 but was 50. Strings differ at index 34.
  Expected: "C:\\Users\\ace.olszowka\\source\\nunit"
  But was:  "C:\\Users\\ace.olszowka\\source\\nunit\\bin\\Debug\\net20"
  -------------------------------------------------^

Mirando la fuente, no veo cómo fue posible, por lo que puedo decir, estos valores deberían haber sido idénticos ( _workDirectory y los datos de prueba están configurados en TestContext.CurrentContext.WorkDirectory ) mi único ¿Supongo que hay algún tipo de condición de carrera, tal vez debido a una mala configuración de mi parte?

Segundo error:

Test Name:  StackTracesAreFiltered("WarningInBeginInvoke",4)
Test FullName:  NUnit.Framework.Assertions.WarningTests.StackTracesAreFiltered("WarningInBeginInvoke",4)
Test Source:    C:\Users\ace.olszowka\source\nunit\src\NUnitFramework\tests\Assertions\WarningTests.cs : line 292
Test Outcome:   Failed
Test Duration:  0:00:00.004

Result StackTrace:  at NUnit.Framework.Assertions.WarningTests.StackTracesAreFiltered(String methodName, Int32 maxLineCount) in C:\Users\ace.olszowka\source\nunit\src\NUnitFramework\tests\Assertions\WarningTests.cs:line 310
Result Message: 
Multiple failures or warnings in test:
  1) (Warning message)
  2) Expected the number of lines to be no more than 4, but it was 5:

 1. at NUnit.TestData.WarningFixture.<>c__DisplayClass45_0.<WarningInBeginInvoke>b__0()
 2. at System.Runtime.Remoting.Messaging.StackBuilderSink._PrivateProcessMessage(IntPtr md, Object[] args, Object server, Object[]& outArgs)
 3. at System.Runtime.Remoting.Messaging.StackBuilderSink.AsyncProcessMessage(IMessage msg, IMessageSink replySink)
 4. at System.Runtime.Remoting.Proxies.AgileAsyncWorkerItem.ThreadPoolCallBack(Object o)
 5. at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
(end)

Me pierdo en lo que esta prueba intenta hacer aquí; pero según mi comprensión limitada, parece que este código es realmente sensible a cualquier cambio en la pila de llamadas, ¿podría esto deberse a un cambio reciente en .NET Framework?

También obtengo todos los casos de prueba que fallan en NUnitLite.Tests.CommandLineTests Me complacería profundizar allí si esto es inesperado.

Dado que la compilación está pasando en CI, probablemente sean solo problemas de configuración de mi parte, pero no se mencionó nada en BUILDING.md sobre esto, así que pensé que valía la pena un informe.

bug normal

Todos 31 comentarios

¡Gracias por el informe! Confirmé que TestCaseSourceCanAccessWorkDirectory y CommandLineTests no funcionan en el Explorador de pruebas. Necesitamos encontrar una manera de hacerlos independientes del corredor y del paralelismo. @ nunit / framework-team ¿Alguna idea?

Para el segundo error, es una prueba de olor. Tiene sentido aumentar eso a 5.

En el pasado, le dije a la gente que no usara el explorador de pruebas para las pruebas de NUnit. Otros miembros del equipo han rechazado ese dicho de que el explorador de pruebas se ha convertido, para muchas personas, en la forma predeterminada de ejecutar pruebas.

Ciertamente, existe un amplio precedente de que un corredor en particular no sea útil al probar un marco de prueba. Los marcos de prueba bajo prueba son una situación bastante especial y no la encuentran la mayoría de los usuarios. OTOH, si el equipo lo desea, tal vez se convierta en un objetivo poder ejecutar con éxito el explorador de prueba a través del adaptador.

Hagas lo que hagas, creo que probablemente deberías publicar alguna documentación que le diga a la gente que ejecutar pruebas NUnit bajo el explorador de pruebas no funciona actualmente. Puede decirles en ese contexto que es un objetivo hacer que funcione o que no es una prioridad, lo que se decida.

Como primer autor del adaptador y colaborador del marco durante muchos años, siempre he criticado el uso del explorador de pruebas en el desarrollo de NUnit. Esa sigue siendo mi opinión sobre el tema. ¡¡¡Ni siquiera me gusta que usemos la consola para probar el marco en nuestro CI ahora !!!

Cualquiera que sea la decisión, creo que tendrá que seguir enviando personas a los corredores NUnit reales (ya sea NUnitLite o el corredor de la consola) cuando surjan problemas que pueden o no deberse al adaptador. El adaptador sigue siendo fundamentalmente equivalente a un corredor de terceros, incluso si está bajo el Proyecto NUnit.

FWIW desde afuera mirando hacia adentro: Realmente no me importa en qué dirección se corte, siempre que esté documentado como tal.

Fuera de la caja, yo, como desarrollador, intentaré hacer lo que haría normalmente cuando me encuentre con un proyecto nuevo que utilice las mismas prácticas que uso internamente:

  1. Clonar el código
  2. Lea el archivo README.md/BUILD.md/HACKING.md
  3. Intentar una compilación (sin cambios)
  4. Ejecute las pruebas unitarias (a través del corredor integrado).
  5. Si todo funciona, empieza a jugar con cosas.

En el pasado, esto habría sido dotCover de ReSharper, pero hemos estado tratando de deshacernos de él ya que los costos de licencia son una locura para las pequeñas tiendas / desarrolladores individuales cuando hay alternativas de software libre / de código abierto que "en su mayoría funcionan".

Hay mucho (en mi opinión) en el concepto de entorno de desarrollo integrado, no tener que salir del flujo de trabajo es muy útil, por eso lo hacemos.

Sin embargo, si se espera que usemos Console Runner (o algún otro Runner) está bien en mi mente, simplemente documente.

Si está desarrollando en NUnit, trabajando en el marco, creo que mezclar cualquier corredor que haga las cosas de maneras especiales (R #, nuestro propio adaptador) puede confundir el problema. Me gusta saber que el marco funciona correctamente de forma aislada antes de probarlo con los corredores. Entonces, en mi propio trabajo, uso nunitlite para probar mientras desarrollo y luego ejecuto el CI localmente. Si una persona quisiera desarrollar en NUnit en Test Explorer, yo diría que aún debería ejecutar CI localmente y también debería recurrir a nunitlite o nunit3-console cuando algo parezca dudoso.

Para las personas que solo ejecutan las pruebas nunit de una versión en particular, creo que hay mucha más libertad.

Deberíamos hacer que CI sea canónico, probablemente con NUnitLite para todas las pruebas de marco y luego la Consola, el adaptador VSTest y un corredor de UWP para las pruebas de un extremo a otro.

Suponiendo que CI es sólido, me parece bien si hay diferencias sutiles entre Test Explorer, ReSharper, NCrunch y nuestro script de CI. Decir que estas herramientas en IDE deben ignorarse es algo que veo como una barrera para la contribución y es falso, ya que ni siquiera es mi flujo de trabajo. Mi flujo de trabajo ideal:

  1. Busque pruebas existentes o escriba nuevas pruebas
  2. Fije ese dispositivo de prueba para que sea más rápido volver a ejecutar las pruebas mientras escribe (incluso mejor, comience la prueba continua)
  3. Implementar un cambio
  4. Antes de crear una confirmación de Git, ejecute .\build.ps1 -t test para asegurarse de que las aprobaciones y las fallas sean las esperadas
  5. Si hay alguna sorpresa, busque y fije las pruebas afectadas que no conocía y vaya al paso 3

En el raro escenario en el que las pruebas son sensibles a los corredores, no estoy seguro de que sea un desafío hacerlas insensibles a los corredores. No puede ser peor que las pruebas de integración que escribí para ILMerge que hice resistentes a las instantáneas de ReSharper y NCrunch.

@aolszowka Estoy 100% de acuerdo con su punto de que, hagamos lo que hagamos, debemos respetar el tiempo de los colaboradores manteniendo los documentos de contribución fáciles de consumir y actualizados.

@ jnm2 Me gusta tu enfoque "canónico". Dudo que sea fácil hacer que todo funcione sin problemas en el Explorador de pruebas, pero vale la pena intentarlo.

Sigue siendo útil, esencial, para cualquier persona que trabaje en nunit saber cuándo cambiar a un nivel más bajo de pruebas.

Lo más importante que podríamos hacer para hacer avanzar esta idea, en mi opinión, es establecer un sistema separado y tal vez pruebas de integración.

Ésta puede ser la causa raíz. Mientras escribía pruebas para obtener XML de FrameworkController, noté que TestContext.WorkDirectory estaba cambiando a C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\Common7\IDE :

https://github.com/nunit/nunit/blob/81fcc7c047c09fcb5a86989d0829716ca7d08e1e/src/NUnitFramework/framework/Api/DefaultTestAssemblyBuilder.cs#L137

Pila de llamadas:

>   nunit.framework.dll!NUnit.Framework.Api.DefaultTestAssemblyBuilder.Build(System.Reflection.Assembly assembly, string suiteName, System.Collections.Generic.IDictionary<string, object> options) Line 137    C#
    nunit.framework.dll!NUnit.Framework.Api.DefaultTestAssemblyBuilder.Build(string assemblyNameOrPath, System.Collections.Generic.IDictionary<string, object> options) Line 114    C#
    nunit.framework.dll!NUnit.Framework.Api.NUnitTestAssemblyRunner.Load(string assemblyNameOrPath, System.Collections.Generic.IDictionary<string, object> settings) Line 154   C#
    nunit.framework.dll!NUnit.Framework.Api.FrameworkController.LoadTests() Line 204    C#

Es porque TestContext.WorkDirectory es un estado mutable estático:

https://github.com/nunit/nunit/blob/81fcc7c047c09fcb5a86989d0829716ca7d08e1e/src/NUnitFramework/framework/TestContext.cs#L96 -L101

Eso significa que es compartido por todas las pruebas (!), Incluidas las simultáneas. Cualquier prueba que se base en WorkDirectory debe estar marcada como [NonParallelizable] para que sea correcta.

Noté este problema hace mucho tiempo. Hay un problema al respecto en alguna parte.

NonParallelizable no es suficiente. Si alguna prueba modifica WorkDirectory (como hacen muchas de las pruebas NUnit), existe una probabilidad razonable de que fallen otras pruebas que dependen de ella.

Todo depende del orden en que se ejecuten las pruebas, que no está definido en NUnit.

La intención es que el directorio de trabajo se establezca una vez y no se modifique durante la ejecución. Cualquier otra cosa es un error.

¿Hay alguna razón por la que no podemos permitir un directorio de trabajo independiente para cada contexto de ejecución?

@CharliePoole ¿Cómo lo haríamos realidad? Estamos en una posición especial ya que el marco prueba FrameworkController, un controlador que se ejecuta dentro de un controlador.

Dejando de lado nuestras pruebas, el significado de WorkDirectory es "el directorio establecido por el usuario para recibir todos los archivos de salida para la ejecución". Por lo tanto, una prueba no debería poder cambiarlo.

Para nuestras propias pruebas, necesitamos poder configurarlo, pero esa configuración no debería afectar a otras pruebas si lo hacemos bien. Probablemente no lo estamos haciendo bien. 😜

En caso de apuro, podríamos hacerlo inalterable y dejar de probarlo. <ducks>

Esa es en realidad una idea genial: rastrear si el campo estático se ha configurado y omitir la configuración a partir de entonces. De esa manera es inmutable y no veo ninguna prueba que verifique si DefaultTestAssemblyBuilder establece, ¡así que deberíamos estar bien!

Hay pruebas de NUnit que lo cambian y, si se hace inalterable, pueden fallar.

@oznetmaster He buscado pero no puedo encontrar ninguna prueba de NUnit que lo cambie excepto accidentalmente. ¿Tienes alguno a la mano?

Tendría que buscar en mis archivos.

Ya solucioné el problema en mi compilación de CF haciendo lo que se ha discutido. Solo permite que el valor se establezca una vez. Verifico que sea nulo y, si lo es, permito que se establezca.

                if (options.ContainsKey (FrameworkPackageSettings.WorkDirectory))
                    TestContext.DefaultWorkDirectory = options[FrameworkPackageSettings.WorkDirectory] as string;
                else
                    if (TestContext.DefaultWorkDirectory == null)
                        TestContext.DefaultWorkDirectory = Directory.GetCurrentDirectory ();

Las pruebas que eran el problema eran las que llamaban a DefaultTestAssemblyBuilder.Build con opciones que no incluían FrameworkPackageSettings.WorkDirectory, lo que provocaba que TestContext.DefaultWorkDirectory fuera sobrescrito por CurrentDirectory. Esto significaba que si WorkDirectory se había configurado en la ejecución de nivel superior, la prueba lo sobrescribirá y nunca se restaurará.

¿Parece que sería bueno que adoptemos el mismo enfoque entonces?

Funciona para mi. Mi construcción de CF pasa el 100% de las pruebas NUnit.

@OmicronPersei Si arreglo de @oznetmaster ?

¡Sí! Lo intentaré esta noche

Realmente no puedo reproducir este error debido a que nunit3-vs-adapter # 528 causa otros problemas. Ideas?

@OmicronPersei Oh. No sé. ¿Usar un .runsettings con WorkDirectory configurado correctamente sería una buena solución?

Está bien, lo he intentado. TestCaseSourceCanAccessWorkDirectory tiene éxito pero StackTracesAreFiltered falla con el mismo mensaje / seguimiento de pila en el OP.

Creo que StackTracesAreFiltered debería aumentarse a 5. Es una prueba de olor para que notamos si se agregan nuevos marcos para que podamos asegurarnos de que no se haya salido de control.

¿Qué pasa con TestCaseSourceCanAccessWorkDirectory , o todavía está en el alcance de este PR?

ForTestCaseCanAccessWorkDirectory, ¿la solución de resuelve? Si no, tendremos que investigar más.

No puedo reproducir el problema en mi máquina, la prueba en cuestión pasa por mí.

No se preocupe, alguien más puede hacer esa parte. También me gusta tener relaciones públicas más pequeñas.

Solo estoy tratando de hacer la limpieza de la casa; ¿Hay alguna razón por la que este problema todavía deba estar abierto o podemos cerrarlo con algún tipo de resolución? (Incluso si es WONTFIX).

No, gracias por señalarlo. Clausura.

¿Fue útil esta página
0 / 5 - 0 calificaciones