Es ist ein Memorandum, weil ich in meiner Arbeit eine Umgebung wie einen Titel aufgebaut habe und an verschiedenen Stellen gestolpert bin.
Da es überhaupt keine Unit-Test-Umgebung gibt, haben wir zunächst lokal eine Unit-Test-Umgebung erstellt. Genau wie beim Erstellen einer Unit-Test-Umgebung mit einer gemeinsamen Datenbank können Sie den Unit-Test ausführen, während Sie db mit Docker-Compose starten.
Klicken Sie hier, um ein Docker-Image für oracle12c zu erstellen.
docker-compose.yml
version: '2'
services:
oracle-database:
image: oracle/database:12.1.0.2-ee
container_name: oracle-database
ports:
- 1521:1521
volumes:
- ./startup:/opt/oracle/scripts/startup
environment:
- ORACLE_SID=SID
- ORACLE_PWD=passw0rd
- ORACLE_PDB=pdb
Für die Verbindung mit dieser Datenbank sind einige Vorbereitungen erforderlich.
Bei einer Oracle-Datenbank wird die Datenbank im Benutzer (Schema) erstellt, daher muss zuerst der Benutzer erstellt werden. Es ist mühsam, jedes Mal vom Benutzer erstellten Code in den Testcode zu schreiben. Lassen Sie den Benutzer also beim Start der Datenbank erstellen.
startup/startup.sql
ALTER SESSION SET container = pdb;
GRANT DBA TO PDBADMIN;
GRANT UNLIMITED TABLESPACE TO PDBADMIN;
CREATE USER testuser
IDENTIFIED BY passw0rd
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp;
GRANT DBA TO testuser;
GRANT UNLIMITED TABLESPACE TO testuser;
Das Oracle-Datenbank-Docker-Image führt die SQL-Datei im Startordner als sysdb-Benutzer aus. Ändern Sie daher die Sitzung, um den Benutzer zur steckbaren Datenbank (PDB) hinzuzufügen. Außerdem verfügt PDBADMIN im Ausgangszustand nicht über die Berechtigung, die admin entspricht (warum?). Daher wird die Berechtigung erteilt.
Hier wird der Benutzer als testuser / passw0rd angelegt. Da es nur für Komponententests verwendet wird, verfügt dieser Benutzer auch über Administratorrechte.
tests/test.py
import unittest
import cx_Oracle
import sqlalchemy
class Test(unittest.TestCase):
def setUp(self):
self.sut = ... #Getestete Instanz
dsn = cx_Oracle.makedsn("oracle-database", 1521, service_name = "pdb")
self.testuser = sqlalchemy.create_engine(f"oracle+cx_oracle://testuser:passw0rd@{dsn}")
self.create_testtable()
def tearDown(self):
self.drop_testtable()
def test__testmethod__describe(self):
# SetUp
expected = ...
# Exercise
self.sut.testmethod(...)
# Verify
actual = ...
self.assertEqual(expected, actual)
def create_testtable(self):
self.testuser.execute(f"""
CREATE TABLE testtable (
... define columns ...
)
""")
def drop_testtable(self):
self.testuser.execute("DROP TABLE testtable")
if __name__ == "__main__":
unittest.main()
Ich denke, es gibt verschiedene Möglichkeiten, einen Test zu schreiben, also als Beispiel. Der wichtige Teil hier ist der Teil, der mit der setUp-Methode mit oracle12c verbunden ist. Erstellen Sie einen DSN und verwenden Sie diese Informationen, um eine Verbindungs-URL zu erstellen und eine Verbindungsengine zu erstellen. In sqlalchemy werden verschiedene Verbindungsmethoden beschrieben. Um jedoch eine Verbindung zum PDB herzustellen, müssen Sie eine Verbindung über ServiceName (nicht SID) herstellen und dafür einen DSN erstellen. Ordnen Sie den Hostnamen im DSN dem in docker-compose.yml
definierten Containernamen zu.
Wenn Sie "__init __. Py" für Tests vorbereiten, wird der Komponententest ausgeführt, indem "pytest" an der Wurzel ausgeführt wird.
docker-compose up -d
pytest
Dies wird vorerst die Mindestumgebung festlegen. Es gibt jedoch Probleme mit dieser Umgebung.
Wie Sie sehen können, dauert das Erstellen der ursprünglichen Datenbank nach dem Erstellen des Dockers erheblich, und es dauert etwa 5 bis 10 Minuten, bis die Datenbank endgültig geöffnet ist (= connect). Außerdem schlägt die anfängliche Datenbankkonstruktion selten fehl (obwohl sie mit Docker erstellt wurde). In Anbetracht der Umgebung als Komponententest ist die Handhabung ziemlich schlecht.
Sichern Sie die ursprüngliche Datenbank, um dieses Problem zu lösen. Es gibt einen Grund, hier "Backup" zu sagen. Dies liegt daran, dass diese anfängliche Datenbank nach dem Herstellen einer Verbindung über DBMS ständig in Form eines Überschreibspeichers aktualisiert wird. Das Gleiche gilt, wenn die Datenbank durch Ausführen eines Komponententests verschmutzt wird. Selbst wenn nichts unternommen wird, nimmt die Dateigröße zu und wird immer "schmutziger". Da es nicht zu leugnen ist, dass der Test aufgrund solcher externer Faktoren fehlschlägt, muss die ursprüngliche Datenbank wiederhergestellt werden, die unmittelbar vor dem "Docker-Composeup" gesichert wurde, um eine stabile Testumgebung aufzubauen. Gibt es.
Einige Techniken sind erforderlich, um die ursprüngliche Datenbank zu erstellen und eine Sicherung vorzubereiten. Ein Beispiel wird hier gezeigt.
Erstellen Sie zunächst ein Oracle-Datenbankimage, um die ursprüngliche Datenbank zu erstellen. In diesem Beispiel wird Docker-Compose verwendet, Sie können jedoch einen ähnlichen Docker-Befehl verwenden.
docker-compose-oradata.yml
version: '2'
services:
oracle-database:
image: oracle/database:12.1.0.2-ee
container_name: oracle-database
ports:
- 1521:1521
volumes:
- ./oradata:/opt/oracle/oradata
environment:
- ORACLE_SID=SID
- ORACLE_PWD=passw0rd
- ORACLE_PDB=pdb
docker-compose -f docker-compose-oradata.yml up
Nach der Ausführung wird die ursprüngliche Datenbank im Ordner oradata erstellt. Diese Konstruktion dauert ca. 5-10 Minuten. Im obigen Beispiel befindet es sich nicht im Trennmodus, um zu überprüfen, ob der Zeitpunkt abgelaufen ist oder nicht.
Von nun an ist es wichtig, die Datenbank sofort nach Abschluss des Builds mit Strg + C herunterzufahren. Wenn Sie sich darauf stützen, wird die ursprüngliche Datenbank übergewichtet (ca. 1,5 GB). Sie können es weiterhin bereitstellen, aber es macht keinen Sinn, wenn die von Ihnen gesicherten Dateien unnötig groß sind. Fahren Sie sie daher sofort nach der Erstellung herunter.
Starting oracle-database ... done
Attaching to oracle-database
oracle-database | ORACLE PASSWORD FOR SYS, SYSTEM AND PDBADMIN: passw0rd
oracle-database |
oracle-database | LSNRCTL for Linux: Version 12.1.0.2.0 - Production on 15-OCT-2020 12:03:40
oracle-database |
oracle-database | Copyright (c) 1991, 2014, Oracle. All rights reserved.
oracle-database |
oracle-database | Starting /opt/oracle/product/12.1.0.2/dbhome_1/bin/tnslsnr: please wait...
oracle-database |
oracle-database | TNSLSNR for Linux: Version 12.1.0.2.0 - Production
oracle-database | System parameter file is /opt/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
oracle-database | Log messages written to /opt/oracle/diag/tnslsnr/bf429c874900/listener/alert/log.xml
oracle-database | Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
oracle-database | Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
oracle-database |
oracle-database | Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1)))
oracle-database | STATUS of the LISTENER
oracle-database | ------------------------
oracle-database | Alias LISTENER
oracle-database | Version TNSLSNR for Linux: Version 12.1.0.2.0 - Production
oracle-database | Start Date 15-OCT-2020 12:03:40
oracle-database | Uptime 0 days 0 hr. 0 min. 0 sec
oracle-database | Trace Level off
oracle-database | Security ON: Local OS Authentication
oracle-database | SNMP OFF
oracle-database | Listener Parameter File /opt/oracle/product/12.1.0.2/dbhome_1/network/admin/listener.ora
oracle-database | Listener Log File /opt/oracle/diag/tnslsnr/bf429c874900/listener/alert/log.xml
oracle-database | Listening Endpoints Summary...
oracle-database | (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC1)))
oracle-database | (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
oracle-database | The listener supports no services
oracle-database | The command completed successfully
oracle-database | Cleaning up failed steps
oracle-database | 4% complete
oracle-database | Copying database files
oracle-database | 5% complete
oracle-database | 6% complete
oracle-database | 30% complete
oracle-database | Creating and starting Oracle instance
oracle-database | 32% complete
oracle-database | 35% complete
oracle-database | 36% complete
oracle-database | 37% complete
oracle-database | 41% complete
oracle-database | 44% complete
oracle-database | 45% complete
oracle-database | 48% complete
oracle-database | Completing Database Creation
oracle-database | 50% complete
oracle-database | 53% complete
oracle-database | 55% complete
oracle-database | 63% complete
oracle-database | 66% complete
oracle-database | 74% complete
oracle-database | Creating Pluggable Databases
oracle-database | 79% complete
oracle-database | 100% complete
oracle-database | Look at the log file "/opt/oracle/cfgtoollogs/dbca/SID/SID0.log" for further details.
oracle-database |
oracle-database | SQL*Plus: Release 12.1.0.2.0 Production on Thu Oct 15 12:11:34 2020
oracle-database |
oracle-database | Copyright (c) 1982, 2014, Oracle. All rights reserved.
oracle-database |
oracle-database |
oracle-database | Connected to:
oracle-database | Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
oracle-database | With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
oracle-database |
oracle-database | SQL>
oracle-database | System altered.
oracle-database |
oracle-database | SQL>
oracle-database | Pluggable database altered.
oracle-database |
oracle-database | SQL> Disconnected from Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
oracle-database | With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
oracle-database | The Oracle base remains unchanged with value /opt/oracle
oracle-database | #########################
oracle-database | DATABASE IS READY TO USE!
oracle-database | #########################
oracle-database | The following output is now a tail of the alert.log:
oracle-database | Completed: alter pluggable database PDB open
oracle-database | Thu Oct 15 12:11:33 2020
oracle-database | CREATE SMALLFILE TABLESPACE "USERS" LOGGING DATAFILE '/opt/oracle/oradata/SID/PDB/PDB_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT 1280K MAXSIZE UNLIMITED EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO
oracle-database | Completed: CREATE SMALLFILE TABLESPACE "USERS" LOGGING DATAFILE '/opt/oracle/oradata/SID/PDB/PDB_users01.dbf' SIZE 5M REUSE AUTOEXTEND ON NEXT 1280K MAXSIZE UNLIMITED EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO
oracle-database | ALTER DATABASE DEFAULT TABLESPACE "USERS"
oracle-database | Completed: ALTER DATABASE DEFAULT TABLESPACE "USERS"
oracle-database | Thu Oct 15 12:11:34 2020
oracle-database | ALTER SYSTEM SET control_files='/opt/oracle/oradata/SID/control01.ctl' SCOPE=SPFILE;
oracle-database | ALTER PLUGGABLE DATABASE PDB SAVE STATE
oracle-database | Completed: ALTER PLUGGABLE DATABASE PDB SAVE STATE
^CERROR: Aborting.
Sichern Sie den oradata-Ordner irgendwo, damit der Inhalt dieses oradata-Ordners wiederhergestellt wird, bevor Sie "docker-compose up" ausführen, bevor Sie den Test ausführen (im eigentlichen Geschäft sollte der Inhalt von oradata wiederhergestellt werden. Reißverschluss komprimiert und auf S3 gesichert). Die ursprüngliche Datei docker-compose.yml sollte den Ordner oradata bereitstellen.
docker-compose.yml
version: '2'
services:
oracle-database:
image: oracle/database:12.1.0.2-ee
container_name: oracle-database
ports:
- 1521:1521
volumes:
- ./oradata:/opt/oracle/oradata
- ./startup:/opt/oracle/scripts/startup
environment:
- ORACLE_SID=SID
- ORACLE_PWD=passw0rd
- ORACLE_PDB=pdb
Auf diese Weise konnte die Zeit zum Öffnen der Datenbank auf etwa 1 bis 2 Minuten reduziert werden.
Das Hauptthema.
Wenn Sie eine Datenbank für Unit-Tests auf GitLab CI verwenden, ist es ein königlicher Weg, "Dienste" zu verwenden. Das Image der Oracle-Datenbank muss jedoch von einer Art privatem Repository verwaltet werden. Ich habe noch nie ein privates Repository in Services eingerichtet und in der Praxis andere Docker-Images erstellt. Daher werde ich hier Docker in Docker (dind) verwenden. Ich habe eine Umgebung gebaut.
Beim Erstellen einer Dind-Umgebung mit GitLab CI gibt es ein Problem. Das heißt, das Verzeichnis, in dem das Volume bereitgestellt wird, wird zum Hostverzeichnis. Normalerweise (nicht auf GitLab CI beschränkt) erfolgt die Jobausführung selbst im Docker-Container. Wenn Sie also Docker-Compose wie folgt ausführen, befinden sich die Ordner oradata und startup im Docker-Container, in dem der Job ausgeführt wurde. Stattdessen geben Sie am Ende den Ordner auf dem Host an, auf dem dieses Docker ausgeführt wird.
Es gibt verschiedene Lösungen dafür, aber dieses Mal habe ich es vermieden, indem ich ein Docker-Image erstellt habe, das Oradata enthält. Da das Oracle-Datenbank-Image in erster Linie in einem privaten Repository abgelegt werden sollte, wird das Image einschließlich Oradata nur dort vorbereitet, sodass sich an der lokalen Umgebung nicht viel ändert.
Die Docker-Datei, die das Oracle-Datenbank-Image einschließlich der zuvor erstellten Oradata erstellt, sieht folgendermaßen aus.
Dockerfile
FROM oracle/database:12.1.0.2-ee
ENV ORACLE_SID SID
ENV ORACLE_PWD passw0rd
ENV ORACLE_PDB pdb
COPY --chown=oracle:dba oradata/ /opt/oracle/oradata/
COPY startup/ /opt/oracle/scripts/startup/
docker build -t oracle/database:12.1.0.2-ee-with-oradata
Es gibt zwei Punkte zu beachten.
Erstens hängen oradata von den Umgebungsvariablen ORACLE_SID, ORACLE_PWD und ORACLE_PDB ab. Fügen Sie diese Umgebungsvariablen also auch zu Ihrer Docker-Datei hinzu. Wenn sich diese ändern, erstellen Sie auch oradata neu.
Die andere Möglichkeit besteht darin, den Besitzer beim Kopieren von Oradata in "oracle: dba" zu ändern. Wenn Sie es so kopieren, wie es ist, wird es zum Root-Benutzer, und der Oracle-Benutzer kann die ursprüngliche Datenbank nicht bereitstellen.
Verwenden Sie dann dieses Image und führen Sie es in .gitlab-ci.yml aus.
docker-compose.yml
version: '2'
services:
oracle-database:
image: oracle/database:12.1.0.2-ee-with-oradata
container_name: oracle-database
ports:
- 1521:1521
yml:.gitlab-ci.yml
pytest:
stage: test
image: docker:dind
script:
- apk update && apk add bash python3 python3-dev py3-pip docker-compose
- python3 -m pip install pytest
- docker-compose up -d
- sleep 120s
- pytest
(Ich bin nicht sicher, ob ich eine Ausführungsumgebung für pytest erstellen soll. Ich werde es später überprüfen.)
Da das Öffnen der ursprünglichen Datenbank einige Zeit in Anspruch nimmt, verwenden wir hier als Beispiel "sleep 120s".
Auf diese Weise wurde es vorerst möglich, Unit-Tests mit der Oracle-Datenbank auf GitLab CI durchzuführen.
Recommended Posts