Pregunta

He oído que la unidad de pruebas es "totalmente increíble", "muy interesante" y "toda clase de cosas buenas", pero el 70% o más de mis archivos de involucrar a la base de datos de acceso (leer y escribir algunos) y no estoy seguro de cómo se escribe una unidad de prueba para estos archivos.

Estoy usando PHP y Python, pero creo que es una pregunta que se aplica a la mayoría de los/todos los idiomas que utilizan la base de datos de access.

¿Fue útil?

Solución

Yo sugeriría burla a cabo sus llamadas a la base de datos.Los simulacros son, básicamente, los objetos que se parecen al objeto que está tratando de llamar a un método, en el sentido de que tienen las mismas propiedades, métodos, etc.disponible para la persona que llama.Pero en lugar de realizar cualquier acción que están programados para hacer cuando un particular método es llamado, se omite por completo, y sólo devuelve un resultado.Ese resultado es normalmente definido por usted antes de tiempo.

Con el fin de establecer sus objetos de burla, es probable que necesite usar algún tipo de inversión de control/ patrón de inyección de dependencias, como en el siguiente pseudo-código:

class Bar
{
    private FooDataProvider _dataProvider;

    public instantiate(FooDataProvider dataProvider) {
        _dataProvider = dataProvider;
    }

    public getAllFoos() {
        // instead of calling Foo.GetAll() here, we are introducing an extra layer of abstraction
        return _dataProvider.GetAllFoos();
    }
}

class FooDataProvider
{
    public Foo[] GetAllFoos() {
        return Foo.GetAll();
    }
}

Ahora en su unidad de prueba, de crear un simulacro de FooDataProvider, que le permite llamar al método GetAllFoos sin tener que golpear la base de datos.

class BarTests
{
    public TestGetAllFoos() {
        // here we set up our mock FooDataProvider
        mockRepository = MockingFramework.new()
        mockFooDataProvider = mockRepository.CreateMockOfType(FooDataProvider);

        // create a new array of Foo objects
        testFooArray = new Foo[] {Foo.new(), Foo.new(), Foo.new()}

        // the next statement will cause testFooArray to be returned every time we call FooDAtaProvider.GetAllFoos,
        // instead of calling to the database and returning whatever is in there
        // ExpectCallTo and Returns are methods provided by our imaginary mocking framework
        ExpectCallTo(mockFooDataProvider.GetAllFoos).Returns(testFooArray)

        // now begins our actual unit test
        testBar = new Bar(mockFooDataProvider)
        baz = testBar.GetAllFoos()

        // baz should now equal the testFooArray object we created earlier
        Assert.AreEqual(3, baz.length)
    }
}

Un común burlarse de escenario, en una cáscara de nuez.Por supuesto, probablemente desee unidad de prueba de su actual base de datos de llamadas, para la que se necesita para golpear la base de datos.

Otros consejos

Idealmente, los objetos deben ser persistentes ignorante.Por ejemplo, usted debe tener una "capa de acceso a datos", que haría las solicitudes, que devuelven objetos.De esta manera, usted puede dejar que fuera parte de su unidad de pruebas, o prueba de ellos en aislamiento.

Si los objetos están estrechamente junto a su capa de datos, es difícil hacer la prueba de unidad.la primera parte de la unidad de prueba, es la "unidad".Todas las unidades deben ser capaces de ser probado en el aislamiento.

En mis proyectos de c#, puedo usar NHibernate con una completamente separados de la capa de Datos.Mis objetos viven en el núcleo del modelo de dominio y se accede a ellos desde mi capa de aplicación.La capa de aplicación le habla a la capa de datos y la capa de modelo de dominio.

La capa de aplicación es también a veces se llama la "Capa de Negocio".

Si está usando PHP, crear un conjunto específico de clases para SÓLO acceso a los datos.Asegúrese de que los objetos tienen ni idea de cómo se mantiene y el alambre hasta los dos en sus clases de aplicación.

Otra opción sería el uso de burla/stubs.

La manera más fácil de unidad de prueba de un objeto con acceso a base de datos es mediante la transacción ámbitos.

Por ejemplo:

    [Test]
    [ExpectedException(typeof(NotFoundException))]
    public void DeleteAttendee() {

        using(TransactionScope scope = new TransactionScope()) {
            Attendee anAttendee = Attendee.Get(3);
            anAttendee.Delete();
            anAttendee.Save();

            //Try reloading. Instance should have been deleted.
            Attendee deletedAttendee = Attendee.Get(3);
        }
    }

Esto va a revertir el estado de la base de datos, básicamente, como una reversión de transacciones para poder ejecutar la prueba tantas veces como desee sin ningún tipo de efectos colaterales.Hemos utilizado este método con éxito en proyectos de gran envergadura.Nuestra generación necesita un poco de tiempo para funcionar (15 minutos), pero no es horrible por haber 1800 unidad de pruebas.También, si el tiempo de construcción es una preocupación, usted puede cambiar el proceso de construcción para tener varias versiones, una para la construcción de src, otro que se enciende después de que se encarga la unidad de pruebas, análisis de código, embalaje, etc...

Usted debe burlarse de la base de datos de acceso si desea la unidad de prueba de sus clases.Después de todo, usted no quiere a la prueba de la base de datos en una unidad de prueba.Eso sería una prueba de integración.

Resumen de las llamadas de distancia y, a continuación, insertar una maqueta de la que sólo devuelve los datos esperados.Si las clases no hacen más que ejecutar consultas, puede incluso no ser que vale la pena probarlos, aunque...

Tal vez puedo darle un sabor de nuestra experiencia, cuando nos empezó a mirar en nuestra unidad de pruebas de nivel medio de proceso que incluyó una tonelada de "lógica de negocio" operaciones sql.

Primero creamos una capa de abstracción que nos permite "ranura" una razonable conexión de base de datos (en nuestro caso, nosotros simplemente apoyada de una sola ODBC-tipo de conexión).

Una vez en el lugar, fueron capaces de hacer algo como esto en nuestro código (trabajamos en C++, pero estoy seguro de que usted consigue la idea):

GetDatabase().ExecuteSQL( "INSERT INTO foo ( bla, bla )" )

En condiciones normales de tiempo de ejecución, GetDatabase() devolverá un objeto que alimenta a todos nuestros sql (incluyendo consultas), a través de ODBC directamente a la base de datos.

Entonces comenzamos a mirar en memoria de las bases de datos - el mejor por un largo camino parece ser SQLite.(http://www.sqlite.org/index.html).Es muy simple de configurar y usar, y nos ha permitido subclase y reemplazar GetDatabase() para enviar sql a una base de datos en memoria que fue creado y destruido por cada prueba realizada.

Todavía estamos en las primeras etapas de esta, pero mirando bien hasta ahora, sin embargo, tenemos que asegurarnos de crear las tablas que se requieren y rellenar con los datos de prueba - sin embargo, hemos reducido la carga de trabajo algo aquí por la creación de un conjunto genérico de funciones auxiliares que se puede hacer mucho de todo esto para nosotros.

En general, se ha ayudado enormemente con nuestro TDD proceso, ya que hacer lo que parece bastante inocuo cambios para corregir ciertos errores pueden tener bastante extraño afecta en otros (difícil de detectar) áreas de su sistema debido a la naturaleza misma de sql y bases de datos.

Obviamente, nuestras experiencias se han centrado en torno a un C++ entorno de desarrollo, sin embargo estoy seguro de que tal vez podría conseguir algo de trabajo similares en PHP/Python.

Espero que esto ayude.

El libro xUnit Patrones de Prueba describe algunas maneras para manejar de pruebas unitarias de código que golpea a una base de datos.Estoy de acuerdo con el resto de la gente que está diciendo que usted no quiere hacer esto porque es lento, pero tienes que hacerlo en algún momento, de la OMI.Burlándose de la db de conexión para la prueba de nivel superior de las cosas es una buena idea, pero echa un vistazo a este libro de sugerencias acerca de las cosas que usted puede hacer para interactuar con la base de datos real.

Las opciones que tiene:

  • Escribir un script que borrará de la base de datos antes de iniciar las pruebas de unidad, a continuación, rellenar db con un conjunto predefinido de datos y ejecutar las pruebas.Usted también puede hacer que antes de cada prueba – que va a ser lento, pero menos propenso a errores.
  • Inyectar la base de datos.(Ejemplo en la pseudo-Java, pero se aplica a todos los OO-idiomas)

    class Database {
     public Result query(String query) {... real db here ...}
    }

    clase MockDatabase se extiende de la Base de datos { público el Resultado de la consulta(consulta de Cadena) { de retorno "simulacro de resultado";} }

    clase ObjectThatUsesDB { público ObjectThatUsesDB(Base de datos db) { este.base de datos = db;} }

    ahora en producción normal del uso de la base de datos y para todas las pruebas que usted acaba de inyectar el simulacro de base de datos que puede crear ad hoc.

  • No utilice DB a todo lo largo de la mayor parte de código (que es una mala práctica, de todos modos).Crear una "base de datos" objeto de que en lugar de devolver con resultados volverá a su estado normal de los objetos (es decir,volverá User en lugar de una tupla {name: "marcin", password: "blah"}) escribir todas las pruebas ad hoc construido real los objetos y escribir una gran prueba que depende de una base de datos que hace que esta conversión funciona OK.

Por supuesto, estos enfoques no son mutuamente excluyentes y se puede mezclar y combinar como usted necesita.

Generalmente trato de romper mis pruebas entre las pruebas de los objetos (y ORM, en su caso) y la prueba de la db.Puedo probar el lado del objeto de las cosas por que se burlaban de los datos de las llamadas de acceso mientras que la prueba de la db lado de las cosas por las pruebas de que el objeto de las interacciones con la base de datos que es, en mi experiencia, suelen ser bastante limitados.

Yo solía frustrarme con la escritura de la unidad de pruebas, hasta que empiezo a burlarse de los datos de acceso a la parte para que yo no tenga que crear una prueba db o generar datos de prueba sobre la marcha.Burlándose de los datos puede generar todo en tiempo de ejecución y asegúrese de que sus objetos de trabajar correctamente con los conocidos entradas.

Nunca he hecho esto en PHP y nunca he usado Python, pero lo que quiero hacer es burlarse de las llamadas a la base de datos.Para hacer que usted puede implementar algunas Coi si la 3ª parte de la herramienta o administrar usted mismo, entonces usted puede implementar algún simulacro de versión de la base de datos de llamadas, que es donde se va a controlar el resultado de que las llamadas falsas.

Una forma simple de Coi se puede realizar sólo mediante la codificación de las Interfaces.Esto requiere algún tipo de orientación a objetos pasando en su código, así que no puede aplicarse a lo que estás haciendo (yo digo que ya todo lo que tienes es la mención de PHP y Python)

Espero que útil, si nada más tienes algunos de los términos de búsqueda en el ahora.

Estoy de acuerdo con el primer post - acceso a base de datos debe ser despojado de distancia en una capa DAO que implementa una interfaz.A continuación, puede probar su lógica en contra de una punta de la aplicación de la capa DAO.

Usted podría utilizar marcos ficticios abstract el motor de base de datos.No sé si PHP/Python tiene algunos, pero para con los lenguajes (C#, Java, etc.) hay un montón de opciones

También depende de cómo se diseñan los de la base de datos de código de acceso, debido a que algunos de diseño son más fáciles de la prueba de unidad que otras como la anterior, para los puestos mencionados.

Unidad de pruebas de la base de datos de acceso es bastante fácil si su proyecto tiene una alta cohesión y un bajo acoplamiento a lo largo.De esta manera usted puede probar sólo las cosas que cada clase en particular sin tener que probar todo a la vez.

Por ejemplo, si la unidad de prueba de la interfaz de usuario de la clase de las pruebas que escribir sólo debe tratar de verificar la lógica dentro de la interfaz de usuario funcionado como se esperaba, no de la lógica de negocio o de la base de datos de acción detrás de esa función.

Si desea que la unidad de prueba de la base de datos real de acceso usted realmente va a terminar con más de un test de integración, ya que va a depender de la pila de red y servidor de base de datos, pero se puede comprobar que el código SQL que hace lo que usted le pidió que hacer.

El poder oculto de las pruebas de unidad para mí personalmente ha sido que me obliga a diseñar mis aplicaciones en una forma mucho mejor de lo que yo podría prescindir de ellos.Esto es porque realmente me ayudó a romper con el "esta función debe hacer de todo" mentalidad.

Lo siento, no tenemos ningún tipo específico de ejemplos de código para PHP/Python, pero si quieres ver una .NET ejemplo tengo un post que describe una técnica que he utilizado para hacer esta misma prueba.

La configuración de los datos de prueba para las pruebas de unidad puede ser un desafío.

Cuando se trata de Java, si utiliza la Primavera de APIs para la unidad de prueba, usted puede controlar las transacciones en un nivel de la unidad.En otras palabras, usted puede ejecutar las pruebas unitarias que implica actualizaciones de base de datos/inserciones o eliminaciones y deshacer los cambios.Al final de la ejecución de dejar todo en la base de datos tal como era antes de empezar la ejecución.Para mí, es tan bueno como se puede conseguir.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top