unitarias pruebas objective objective-c cocoa xcode tdd ocunit

objective-c - pruebas unitarias objective c



Pruebas unitarias de métodos privados en Xcode (7)

Estoy probando el desarrollo impulsado por pruebas en un proyecto de juguete. Puedo hacer que las pruebas funcionen para la interfaz pública de mis clases (aunque todavía estoy en la cerca porque estoy escribiendo más código de prueba que en los métodos que se están probando).

Tiendo a usar muchos métodos privados porque me gusta mantener limpias las interfaces públicas; sin embargo, aún me gustaría usar pruebas en estos métodos.

Como Cocoa es un lenguaje dinámico, todavía puedo llamar a estos métodos privados, pero recibo advertencias en mis evaluaciones de que mi clase puede no responder a estos métodos (aunque es claro que sí). Como me gusta compilar sin advertencias, estas son mis preguntas:

  1. ¿Cómo desactivo estas advertencias en Xcode?
  2. ¿Hay algo más que pueda hacer para desactivar estas advertencias?
  3. ¿Estoy haciendo algo mal al probar las pruebas de "caja blanca"?

¿Cómo desactivo estas advertencias en Xcode?

No lo hagas

¿Hay algo más que pueda hacer para desactivar estas advertencias?

No lo hagas

¿Estoy haciendo algo mal al probar las pruebas de "caja blanca"?

No.

La solución es mover sus métodos privados a una categoría en su propio encabezado. Importe este encabezado tanto en la clase real como en los archivos de implementación de la clase de prueba.


Estaba lidiando con el mismo problema cuando comencé con TDD hace unos días. Encontré este punto de vista muy interesante en el libro de desarrollo de iOS controlado por prueba :

A menudo me han preguntado, "¿Debería probar mis métodos privados?" O la pregunta relacionada "¿Cómo debo probar mis métodos privados?" Las personas que hacen la segunda pregunta han asumido que la respuesta al primero es "Sí" y ahora están buscando para una forma de exponer las interfaces privadas de sus clases en sus suites de prueba.

Mi respuesta se basa en la observación de un hecho sutil: ya has probado tus métodos privados. Al seguir el enfoque de refactorización rojo-verde común en el desarrollo basado en pruebas, diseñó las API públicas de sus objetos para hacer el trabajo que esos objetos deben hacer. Con ese trabajo especificado por las pruebas y la ejecución continua de las pruebas que le aseguran que no ha roto nada, puede organizar las tuberías internas de sus clases como mejor le parezca.

Sus métodos privados ya han sido probados porque todo lo que está haciendo es un comportamiento de refactorización para el cual ya tiene pruebas. Nunca debe terminar en una situación en la que un método privado no se haya probado o no se haya probado por completo, ya que solo se creará cuando vea la oportunidad de limpiar la implementación de métodos públicos. Esto asegura que los métodos privados existen solo para respaldar la clase de que se deben invocar durante la prueba porque definitivamente se invocan desde métodos públicos.



Recuerde que en Objective-C no existen los "métodos privados", y no es solo porque es un lenguaje dinámico. Por diseño, Objective-C tiene modificadores de visibilidad para ivars, pero no para métodos, no es por accidente que puede llamar a cualquier método que desee.

La sugerencia de @Peter es grandiosa. Para complementar su respuesta, una alternativa que he usado (cuando no quiero / necesito un encabezado solo para métodos privados) es declarar una categoría en el archivo de prueba de la unidad . (Utilizo @interface MyClass (Test) como el nombre.) Esta es una gran manera de agregar métodos que serían innecesarios en el código de lanzamiento, como para acceder a ivars a los que tiene acceso la clase bajo prueba. (Esto es obviamente un problema menor cuando se usan propiedades).

Descubrí que este enfoque facilita la exposición y verificación del estado interno, y agrega métodos de solo prueba. Por ejemplo, en este archivo de prueba unitaria , escribí un método -isValid para verificar la corrección de un montón binario. En producción, este método sería una pérdida de espacio, ya que supongo que un montón es válido; solo me preocupo cuando pruebo regresiones de pruebas unitarias si modifico el código.


Si bien tener un encabezado privado o definir su propia categoría probablemente sean soluciones más correctas, también hay otra solución muy simple: convertir el objeto en (id) antes de llamar al método.


Si no desea distribuir sus implementaciones de métodos privados en varios archivos fuente, un refinamiento de la solución de Categoría es definir una Extensión (esencialmente una Categoría anónima - consulte la documentación de Apple ) en un archivo de encabezado que haya sido importado por su clase existente ''implementación y los archivos fuente de prueba de unidades relevantes.

El uso de una extensión le permite al compilador advertirle si la implementación del método privado no está presente en el bloque @implementation principal. Este enlace lo ilustra muy bien.


Trabajo fácil. Pasos: 1. Usted tiene - (NSString *) getTestString; en su archivo m de destino para la interfaz Foo

  1. Agregue una categoría en su archivo de prueba de unidad:

    @interface DemoHomeViewController () - (NSString *) getTestString; @fin

Entonces, haz lo que quieras ahora.