Six conseils pour utiliser PostgreSQL dans les tests fonctionnels

En 2018, travaillant chez Akvelon Inc. J'ai interviewé une personne. Avant l'entrevue, ils m'ont donné sa tâche de test: une petite application Web comme un carnet ou une liste de tâches - React \ TypeScript, C # à l'arrière et MS SQL Server comme stockage persistant. L'application était à la mode: avec une abondance de tests unitaires sur des simulations, emballés dans une image docker - il est clair que la personne a essayé. Et cette solution n'avait qu'un inconvénient - elle ne fonctionnait pas. Absolument. Échec lors de la tentative d'enregistrement d'une nouvelle ligne dans la base de données.



Je me souvenais très bien de cette affaire, car elle mettait en évidence plusieurs problèmes communs à la fois.


Le premier est la fausse confiance des tests unitaires. Même une couverture à 100% du code avec des tests ne garantit pas qu'il ne contient aucune erreur.


– . , . : , production’. , Oracle, H2\HSQLDB, , , production (boolean, group by ).


PostgreSQL 10- 11-. ( ) , .



, : Embedded PostgreSQL Yandex QATools. . :



TestContainers , Docker’ .


otj-pg-embedded. , , HeadHunter DZone. Yandex QATools , otj-pg-embedded Windows MacOS , - . Liquibase Flyway « »:


abstract class DatabaseAwareTestBase {
    @RegisterExtension
    static final PreparedDbExtension embeddedPostgres =
            EmbeddedPostgresExtension.preparedDatabase(
                    LiquibasePreparer.forClasspathLocation("changelogs/changelog.xml"));
}

GitHub.



. PostgreSQL : , .


, , , , , . , .


. , delete from <table> . truncate. , . truncate , cascade:


truncate table tableA;
truncate table tableB cascade;
truncate table tableE;

, : , :


truncate table tableA, tableB, tableC, tableD, tableE;

cascade, ; . , .



, , , . , 11- Postgres ( 11- , 12-). otj-pg-embedded Zonky, , :


testImplementation enforcedPlatform('io.zonky.test.postgres:embedded-postgres-binaries-bom:11.6.0')
testImplementation 'io.zonky.test:embedded-postgres:1.2.6'

, 100% , .


    @Test
    void checkPostgresVersion() {
        final String pgVersion = jdbcTemplate.queryForObject("select version();", String.class);
        assertThat(pgVersion, startsWith("PostgreSQL 11.6"));
    }


, – . Java-, Linux, . , (, ), CI- , .


SQL


: plain SQL . xml, yml , , . , - \ . xml- psql\pgAdmin – . C plain SQL .


<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
            http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
    <changeSet id="orders_table_create_2020-05-09" author="ivan.vakhrushev">
        <createTable tableName="orders">
            <column name="id" type="BIGINT">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="shop_id" type="BIGINT">
                <constraints nullable="false"/>
            </column>
            <column name="buyer_id" type="BIGINT">
                <constraints nullable="false"/>
            </column>
            <column name="status" type="VARCHAR(20)">
            <column name="creation_time" type="TIMESTAMP">
                <constraints nullable="false"/>
            </column>
            <column name="update_time" type="TIMESTAMP"/>
        </createTable>
    </changeSet>
</databaseChangeLog>


--liquibase formatted sql
--changeset ivan.vakhrushev:orders_table_create_2020-05-09
create table if not exists orders
(
    id bigint not null primary key,
    shop_id bigint not null,
    buyer_id bigint not null,
    status varchar(20),
    creation_time timestamp not null,
    update_time timestamp
);


. Java 8 Java 11 . Instant\LocalDateTime. PostgreSQL Timestamp , «» . Java . , «» . , - :


Timestamp.valueOf(localDateTime.truncatedTo(ChronoUnit.MICROS));
Timestamp.from(instant.truncatedTo(ChronoUnit.MICROS));


. , - .
.


All Articles