2010-12-28 16 views
10

Saludos Stackoverflowers,Sockets de prueba de unidad

Tengo una aplicación en la que existe una capa de abstracción de comunicación. Cada aplicación en esta capa, llamada un conector, ofrece mi solicitud con un medio para el intercambio de datos con un compañero conectado (ej .: a través de HTTP, TCP sockets, sockets UDP, etc.).

Por ejemplo, tengo una clase que implementa Connector_Tcp métodos tales como leen, escritura , abierta y estrecha .

Tengo que escribir una prueba unitaria para esa clase. Sé que las pruebas unitarias deberían tener menos dependencias como sea posible. Desafortunadamente, en ese caso, la dependencia es un recurso del sistema: un socket; y no puedo pasar por alto.

Necesito algunos consejos sobre cómo hacer para probar la unidad en esta clase.

En mi opinión, a pesar de que esta clase está utilizando un recurso del sistema, se debe comprobar que todos los otros conectores para asegurarse de que se respeta la norma establecida por mi solicitud.

Me preocupan cosas tales como colisiones vinculantes (Dirección ya en uso errores) y bloqueo. No quiero que la prueba de la unidad falle porque el puerto ya está siendo utilizado por un servicio del sistema que no tiene nada que ver con mi aplicación.

He hecho muchas pruebas unitarias en mis días, pero ninguna de ellas depende de un recurso de bajo nivel como son los zócalos.

Cómo haría usted para pruebas unitarias toma una clase dependiente? Abra un socket para cada unidad? Use una sola clase de servidor, luego un recurso de socket definido manualmente para conectarse y probar ...?

Creo que mi problema realmente es la siguiente:

Si la prueba de unidad no ... ¿cómo sé si:

  • El socket ya está en uso por otro proceso;
  • La prueba de la unidad está mal escrita; o
  • El método se comporta de forma incorrecta (que es lo que vale la prueba de una unidad).

necesito la unidad de prueba para probar si el método se ha estado comportando correctamente o no ...

+1

No he hecho ningún desarrollo de PHP real, pero ¿puedes crear una clase simulada que se deriva de tu clase de Socket? – Dave

+0

@Dave: puedo. Yo uso objetos simulados para cada clase que requiere un conector. Mi problema aquí es: necesito probar la clase de socket para asegurarse de que respeta las convenciones de la capa de abstracción ... Al probar un objeto simulado, no me dice claramente si la clase de socket funciona o no. – netcoder

+0

hay un límite práctico para lo que puede probar en mi opinión. No trataría de probar la unidad en el zócalo. Supongo que en su caso, dado que el socket podría ser accesible fuera de su aplicación, solo tiene que hacer lo mejor que pueda para escribir pruebas de unidad alrededor del conector y asegurarse de que maneje todas las condiciones excepcionales. Mencionaste los errores de "dirección ya en uso", así que una cosa que haría es asegurarme de que mi conector no haya muerto por esta condición. Haría una prueba unitaria para crear esta condición y asegurarme de que la atrape. – Dave

Respuesta

4

He escrito una capa de abstracción similar, aunque en C/C++, y he tenido ocasión de probar la unidad código basado en socket. No sé si hay algo intrínsecamente específico para PHP aquí, así que solo ofreceré los consejos genéricos que pueda.

  • Cree un zócalo de servidor en su configuración, ciérrelo en el desmontaje. Dependiendo de si admite muchos clientes que se conectan al socket del servidor, es posible que desee hacer esa parte en el método de prueba.
  • Suponiendo que puede especificar el puerto para conectarse en su código de cliente, haga que el socket del servidor se enlace al puerto 0 (puerto efímero) y luego utilícelo en el código del cliente. Esto eliminará el problema de vincular a un puerto que ya está en uso.
  • Establezca los tiempos de espera en sus sockets. Si su prueba falla por alguna razón inesperada, no la quiere esperar esperando una conexión para siempre.
  • Debe poder intercalar el comportamiento cliente/servidor. Por ejemplo, querrá probar qué sucede si el servidor cierra su lado de la conexión a la mitad de una lectura/escritura del cliente. E/S asíncrona o multi-threading hará el trabajo. No estoy seguro de lo que tienes a tu disposición en PHP.
+0

Creo que necesitaba consejos de un programador de C, debido a la forma en que se manejan los sockets de PHP. Las funciones de socket en PHP son muy similares a los sockets C (¡incluso usan los mismos nombres constantes!). Habiendo dicho eso, creo que me habías señalado en la dirección correcta.Al enlazar en el puerto 0 y usando 'getsockname', puedo recuperar el número de puerto al que el servidor se ha vinculado y conectarlo a un cliente, sin tener que preocuparme por los puertos que ya están siendo utilizados. ¡Debería haberlo pensado antes! ¡Muchas gracias! – netcoder

+0

Ah, y para conexiones multiproceso y simultáneas múltiples, no debo preocuparme por ello. Hay otra clase que se ocupa de esto, así que todo lo que necesito aquí es probar el socket. – netcoder

2

espero estar comprender adecuadamente su pregunta ... si no, por favor me deje saber. Pero lo que haría es burlarse del zócalo. Eso le permitiría escribir una serie de pruebas unitarias que garanticen que su método haga todas las cosas correctas en varios casos.

Por ejemplo, podría escribir una prueba de unidad que le dice a la toma ejemplo simulacro de lanzar un "puerto no está disponible" excepción. En ese caso, podría afirmar que su método detectó la excepción y la registró con el mismo texto que estaba en la excepción.

Y más importante aún, podría escribir una prueba unitaria que indique a la instancia del simulador de socket que devuelva un flujo válido de bytes de read(), y luego podría afirmar que su método hace lo correcto (s) con esos bytes.

Así que en realidad no estás probando el socket. Estás configurando el socket para simular ciertas ocurrencias, y estás probando para ver si tu código que funciona con el socket está haciendo las cosas correctas.

(He utilizado frameworks de burla en Java, C#, Ruby y JavaScript. Nunca he trabajado con PHP, pero apuesto a que hay algunos buenos frameworks burlones para eso).

EDITAR: Sí, hay algunos marcos de burla para PHP. No puedo recomendar uno, pero aquí hay un par que pude encontrar: PHPUnit y LastCraft

+0

Gracias por su respuesta. Ya estoy usando PHPUnit. Desafortunadamente, a diferencia de Java y C#, que también sé, los sockets en PHP están muy cerca de los zócalos C/C++. De hecho, PHP usa un contenedor para la biblioteca C. Los sockets de PHP no son objetos, sino que se consideran recursos (más o menos punteros), que se parecen más a un tipo primitivo, por lo que no se pueden burlar. Mis clases son envoltorios para esas funciones de socket, y necesito asegurarme de que devuelvan * false *, * null * o datos cuando sea necesario, sin fallas debido a colisiones. Creo que @axw podría tener la respuesta que necesito. ¡Muchas gracias! – netcoder