News
Das Neuste aus der Welt von Adfinis SyGroup
Es gibt (immer) noch diverse Server im Internet, die keine oder nur eine unzureichende SSL/TLS Konfiguration haben. Es handelt sich dabei nicht nur um Webserver (wie nginx oder Apache), sondern auch z.B. um XMPP/Jabber Server und Mailserver. Als Grundlage jeder SSL/TLS Konfiguration werden Keys und Zertifikate sowie allfällig auch noch Diffie-Hellman-Parameter benötigt. Dieser Artikel soll die wichtigsten Kommandos von OpenSSL zusammenfassen und kurz erklären.
Keys und Zertifikate erstellen
Um private Schlüssel und Zertifikate von Hand zu erstellen, kommen nachfolgend diverse nützliche Kommandos und deren Erklärungen.
Formate
Es gibt verschiedene Formate, wie Zertifikate und Keys gespeichert werden können. Nachfolgend wird immer das PEM-Format genutzt, dieses wird von den meisten Tools am besten unterstützt, die Dateien sind jedoch grösser als z.B. das DER-Format, da PEM aus ASCII Zeichen besteht und DER binär ist. Typische Endungen für PEM Zertifikate sind .pem
oder .crt
. Zertifikate im DER-Format sollten jeweils die Endung .der
haben.
Das PEM-Format ist einfach zu erkennen, da der Inhalt der Dateien mit -----BEGIN CERTIFICATE-----
anfängt und mit -----END CERTIFICATE-----
endet. Ein guter Überblick der Formate und deren Umwandlung in jeweils andere Formate ist auf ssl.com erklärt.
Eine Liste der gängigsten Formate ist folgende:
- PEM: Endung
.pem
,.crt
,.cer
- DER: Endung
.der
- PKCS#7: Endung
.p7b
,.p7c
- PKCS#12: Endung
.p12
- PFX: Endung
.pfx
Certificate Signing Request erstellen
Certificate Signing Requests (CSR) sind Anträge für neue Zertifikate. Diese müssen anschliessend entweder von einer Certificate Authority (CA) oder Self-Signed unterschrieben werden. Damit ein CSR erstellt werden kann, braucht es zuerst einen privaten Schlüssel. Normalerweise muss jedes mal wenn ein Zertifikat beantragt wird, ein neuer Certificate Signing Request erstellt werden.
Im ersten Schritt wird ein RSA Key mit 4096 Bit erstellt. Dies kann nach heutigen Standards als sicher angeschaut werden. Im zweiten Schritt wird der CSR erstellt, welcher mit SHA256 signiert wird (viele default Werte sind noch SHA1, deshalb sollte zwingend SHA256 explizit angegeben werden). Weitere Informationen zum Erstellen von RSA Keys kann in der Manpage von genrsa
bzw. req
für Certificate Signing Requests nachgelesen werden.
$ openssl genrsa -out example.com.key 4096
$ openssl req -new -sha256 -key example.com.key -out example.com.csr
Dies ist auch in einem Schritt möglich. Hier wird direkt ein CSR erstellt und dazu OpenSSL noch aufgefordert, den entsprechenden privaten Schlüssel zu erstellen.
$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout example.com.key -out example.com.csr
Self-signed Certificate erstellen
Um schnell SSL Konfigurationen zu testen oder auf Servern, auf welchen nie geprüft wird, ob ein Zertifikat auch korrekt von einer Certificate Authority signiert wurde, können self-signed Zertifikate verwendet werden. Diese zu erstellen ist mit folgendem Kommando möglich. Es erstellt einen privaten Schlüssel, generiert daraus eine Certificate Signing Request und signiert diese mit dem privaten Schlüssel. Daraus folgt das Zertifikat, welches in example.com.pem
abgelegt wird.
$ openssl req -x509 -sha256 -nodes -newkey rsa:4096 -keyout example.com.key -days 730 -out example.com.pem
Eigene CA erstellen und damit die Zertifikate signieren
Normale Zertifikate sollten die Berechtigung zum Signieren anderer Zertifikate nicht haben, dafür sollten spezielle Zertifikate zum Einsatz kommen, sogenannte Certificate Authorities (CA).
Ist die Anzahl der Clients überschaubar oder in anderen speziellen Fällen, kann eine eigene Certificate Authority (CA) erstellt werden. Dies ist zum Beispiel bei vielen Virtual Private Networks (VPN) nötig, da dort das Zertifikat des Servers und aller Clients signiert werden müssen.
Zuerst erstellen wir eine Datei (Dateiname z.B. x509.ext
), in welcher die x509 Extensions definiert sind. Es gibt dafür zwei Abschnitte, den für die CA und den für Server Zertifikate.
[ ca ]
# X509 extensions for a ca
keyUsage = critical, cRLSign, keyCertSign
basicConstraints = CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always
[ server ]
# X509 extensions for a server
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth,clientAuth
basicConstraints = critical,CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
Danach erstellen wir die CA und die Server Zertifikate.
Im ersten Schritt wird ein neuer privater Schlüssel und ein Zertifikat erstellt, welches danach als Certificate Authority dient. Das Zertifikat der Certificate Authority hat in diesem Beispiel ein Ablaufdatum von 3 Jahren. Dieses Zertifikat darf nur zum Signieren weiterer Zertifikate genutzt werden (dies ist im Extension File im Abschnitt ca
definiert).
Im zweiten Schritt wird das Server Zertifikat erstellt und von der CA signiert. Dem Zertifikat des Servers wird ein Ablaufdatum von 2 Jahren gesetzt. Weiter wird ein CA serial number File erstellt, wenn es nicht schon vorhanden ist. Dieses wird von der CA benötigt, damit die CA die aktuelle Seriennummer kennt. Das Server Zertifikat wird beim Signieren darauf eingeschränkt, dass es nur als Server oder Client agieren und keine weiteren Zertifikate signieren darf. Weitere Informationen sind in der Manpage von x509
und x509v3_config
enthalten.
$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout CA.key -out CA.csr
$ openssl x509 -req -sha256 -extfile x509.ext -extensions ca -in CA.csr -signkey CA.key -days 1095 -out CA.pem
$ openssl req -new -sha256 -nodes -newkey rsa:4096 -keyout www.example.com.key -out www.example.com.csr
$ openssl x509 -req -sha256 -CA CA.pem -CAkey CA.key -days 730 -CAcreateserial -CAserial CA.srl -extfile x509.ext -extensions server -in www.example.com.csr -out www.example.com.pem
Certificate und Certificate Signing Requests betrachten
Der Inhalt von Zertifikaten und Certificate Signing Requests kann am besten mit OpenSSL dargestellt werden. Nebst dem gesamten Inhalt (Option -text
) können auch nur Teile davon dargestellt werden, so kann zum Beispiel das Erstell- und Ablaufdatum mit -dates
dargestellt werden. Die entsprechende Liste ist in der Manpage (man 1 x509
) unter dem Punkt Display options
zu finden.
- Certificate
$ openssl x509 -in example.com.pem -noout -text
- Certificate Signing Request
$ openssl req -in example.com.csr -noout -text
Diffie-Hellman Parameter erstellen
Diffie-Hellman Parameter werden für Forward-Secrecy benötigt. Folgendes Kommando erstellt Diffie-Hellman Parameter mit 4096 Bit. Es ist nicht nötig so grosse Parameter zu erstellen, 2048 sollten auch reichen. Das Erstellen kann je nach Maschine extrem lange dauern. Es kann sich evtl. lohnen diese auf einer Hardware Maschine zu erstellen (da mehr Entropie vorhanden ist) und danach auf die virtuelle Maschine zu transferieren.
$ openssl dhparam -out dh4096.pem 4096
Konvertieren
Zertifikate können mit OpenSSL in andere Formate umgewandelt werden. Teilweise ist ein Zwischenschritt notwendig. Die gängigsten Umwandlungen, von DER zu PEM und umgekehrt, kann mit folgenden Kommandos gemacht werden:
$ openssl x509 -in cert.pem -outform der -out cert.der
und
$ openssl x509 -in cert.der -inform der -outform pem -out cert.pem
Das PKCS#12 und PFX Format kann mit folgenden Kommandos umgewandelt werden.
PFX (privater Schlüssel und Zertifikat) nach PEM (privater Schlüssel und Zertifikat):
$ openssl pkcs12 -in keyStore.pfx -out keyStore.pem -nodes
PEM (privater Schlüssel und Zertifikat) nach PFX (privater Schlüssel und Zertifikat):
$ openssl pkcs12 -export -out certificate.pfx -inkey privateKey.key -in certificate.crt -certfile CACert.crt
Weitere Kommandos zur Umwandlung finden sich auf bereits oben erwähnter Seite (ssl.com).
Sandro Köchli, Mitgründer und Verwaltungsratsmitglied der Adfinis SyGroup, erklärt wie es dazu kam, dass aus der Rivalität zwischen Microsoft und Linux eine Symbiose wurde.
Im Artikel der Netzwoche erfahren Sie mehr über die Geschichte hinter unserer Partnerschaft mit Microsoft und der damit zusammenhängenden Relevanz der Azure Cloud Services.
Cloud ist sexy! Sofort eingerichtet, Wartung und Pflege ist ausgelagert, Ressourcen skalieren ohne Zutun und in vielen Fällen bieten Web-Lösungen mittlerweile Funktionen, die man sich bei Desktop-Lösungen nur wünschen kann.
Seit Google vormacht, wie man online gemeinsam am gleichen Dokument arbeiten kann, merken auch hartgesottene Word-Freaks, dass es bei Textverarbeitung primär um Inhalte geht und diese entstehen nun mal schneller und unkomplizierter, wenn man mit seinen Arbeits- oder StudienkollegInnen direkt am gleichen Text arbeiten kann.
Auch bei Projekt-Management Tools merken selbst die grössten Fans von etablierten Desktop-Lösungen, dass es durchaus praktisch ist, wenn man unkompliziert via Browser den Status eines Tasks aktualisieren kann.
Die Liste solcher Anwendungsfälle liesse sich beliebig erweitern und so erstaunt es nicht, dass immer mehr Workflows ins Web wandern – doch was passiert mit den Daten?
Der Einsatz von Dropbox, Google Docs, SmartSheet und co. hat einen gewichtigen Nachteil: sämtliche Daten wandern in die Hände Dritter und jede Organisation, welche diesen Schritt vollzieht, läuft Gefahr, dass etwelche Firmengeheimnisse in die falschen Hände geraten.
Die Wahl lautet also: die Vorteile der Cloud nutzen oder Datensicherheit garantieren?
Collabora Online – Funktionalität und Datensicherheit
Die Open Source Community hat mit LibreOffice eine Office Suite geschaffen, die längst etabliert ist und in rasantem Tempo weiterentwickelt wird.
Unsere Kollegen bei Collabora zählen zu den wichtigsten Unterstützern dieses Projekts und haben früh erkannt, dass eine webbasierte Lösungen geschaffen werden muss, um auch die neuen Anforderungen an webbasierte Workflows abdecken zu können.
Statt auf Feld 1 neu zu starten und eine komplett neue Office-Lösung für den Browser zu entwickeln, haben die Collabora EntwicklerInnen auf LibreOffice aufgebaut und eine Art Web-Frontend darum gezimmert.
Die so entstandene Lösung ist heisst Collabora Online, ist komplett Open Source, lässt sich auf der eigenen Infrastruktur betreiben und wird durch kommerzielle Support-Dienstleistungen abgerundet.
Wie funktioniert Collabora Online?
Collabora Online besteht im Kern aus einer Server-Komponente, die am einfachsten als eine Art headless LibreOffice beschrieben werden kann.
Dieser Daemon rendert die Dokumente auf dem Server und verwendet dabei die gleiche Code-Basis wie die Desktop Version, nutzt als Zeichnungsfläche jedoch nicht eine GUI, sondern erstellt direkt Bitmap-Repräsentationen der Dokumente. Der Server akzeptiert externe Verbindungen über HTTP(S) und stellt Websockets zur Verfügung, über welche die Kommunikation mit dem Browser verläuft.
Im Client läuft eine HTML/JavaScript-Applikation, die im Kern auf leaflet.js aufbaut. leaflet.js ist im Umfeld von Online-Karten entstanden und man darf sich fragen, wo hier der Zusammenhang besteht. Nun, unterteilt man ein Dokument in 256×256 Pixel grosse Segmente und klatscht eine Zoom-Funktion oben drauf, stellt man schnell fest, dass eine online Repräsentationen eines Dokuments durchaus einer Karten-Darstellung gleicht.
Über dieser „Karten-Darstellung“ des Dokuments schwebt eine (transparente) Ebene, über die der Benutzer mit dem Dokument interagiert. Text markieren, Objekte herumschieben, etc. werden dabei auf diesem Layer getätigt und über den Websocket an den Server geschickt.
Der Server-Dienst rendert das Dokument neu und invalidiert die Bereiche des Dokuments, die neu gezeichnet werden müssen. Die neuen Tiles werden an den Browser geschickt und dieser tauscht die nötigen Bereiche entsprechend aus.
Die Roundtrip-Zeit (Client → Server → Client) hat dabei einen grossen Einfluss darauf, wie flüssig sich das Editieren anfühlt. Diesen Text habe ich über Wifi und eine gewöhnliche VDSL-Leitung geschrieben. Beim Tippen fällt die Latenz dabei auf. Die ping-Zeiten zu dem Host betrugen rund 20ms, doch als all zu störend habe ich diesen Lag nicht empfunden. Beim Herumschieben von Bildern fällt es hingegen eher ins Gewicht.
Funktionsumfang
Der angebotene Funktionsumfang umfasst aktuell ein Subset der Möglichkeiten der Desktop-Anwendungen. Sämtliche Basis-Funktionen stehen jedoch zur Verfügung und funktionieren soweit problemlos.
Es spielt keine Rolle, ob man ein Text-Dokument, eine Tabelle oder eine Präsentation bearbeiten will – alle diese Dateitypen werden gleichermassen unterstützt.
Das kollaborative Editieren sticht aus der Lösung natürlich hervor: ein Dokument kann gleichzeitig von mehreren BenutzerInnen editiert werden. Jeder Cursor wird dabei separat angezeit – genau so, wie man es von Lösungen wie Google Docs auch kennt.
Ausblick
Collabora arbeitet intensiv daran, weitere Funktionen von LibreOffice auch im Browser zugänglich zu machen. Bis Ende 2017 sollen in der online Version viele weitere Funktionen dazu kommen – hier profitiert die Lösung natürlich ungemein davon, dass sämtliche Features auf der Server-Seite bereits implementiert sind und „lediglich“ der Frontend Teil um entsprechende Aufrufe ergänzt werden muss.
Test Zugang
Wir führen aktuell intensive Tests durch und sammeln Erfahrungen im Betrieb der Lösung. Gerne erstellen wir dafür auch Test-Zugänge für interessierte Leserinnen und Leser dieses Blogs. Eine Mail an info@adfinis.com genügt – wir übernehmen aber aktuell noch keine Garantien für die Verfügbarkeit des Dienstes! Die Daten liegen aber auf Servern unserer Infrastruktur und wir stellen definitiv keinen Unfug damit an – versprochen! 🙂
Fazit
Collabora Online hat gehöriges Potential! Die von Collabora erstellte Lösung ist simpel und genial. Die Dokumente werden perfekt gerendert und es gibt eine 100%ige Kompatibilität zwischen der Desktop und der online Version. Schon allein dieser Vorteil ist ein USP für sich. Dass man die Lösung im eigenen Datacenter betreiben kann ist jedoch noch weitaus wichtiger als wenn das nicht schon ausreichen würde: das ganze ist Open Source und selbst kommerzielle Support Angebote mit lokalen Partnern sind schon verfügbar.
Einziger Wermutstropfen: die Round-Trip Zeiten werden bei langsamen Verbindungen ein Problem darstellen. Dies lässt sich wohl mit dem gewählten Ansatz auch zukünftig nicht lösen.
Links
Als Vertriebs- und Integrationspartner von Nextcloud bringen wir die gleichnamige on-premise Lösung für Datenspeicher und Zusammenarbeit auf den Schweizer Markt und bieten unseren Kunden vollumfänglichen Service für die sorgenfreie Nutzung von Nextcloud im Unternehmensumfeld.
Lesen Sie die Pressemitteilung für detaillierte Informationen.
Wer in Python seinen Code testen möchte, sollte sich einmal Pytest als Alternative zu Unittest anschauen.
Pytest ist ein Testing-Framework für Python, welches das Testen sehr einfach und ohne viel Boilerplate ermöglicht. Seine Vorteile liegen in der Einfachheit, automatischem Test-Discovery, modularer Fixtures und intelligenter Fehlerausgabe.
Dieser Blogbeitrag soll einen Überblick und einfachen Einstieg in das Testen mit Pytest geben. Er gibt zuerst eine Übersicht über die Verwendung von Pytest, geht danach darauf ein, wie man Ressourcen für die Tests zur Verfügung stellt und schliesst mit ein paar Tipps und Tricks ab.
Einführung
Tests schreiben
Tests können mit Pytest ganz einfach geschrieben werden. Man benötigt lediglich das Python eigene Assert-Statement. Damit Pytest den Test auch findet, stellt man der Test-Funktion das Präfix `test_` voran:
def test_blog():
assert 1 > 0
Mehr ist zum Testen nicht nötig!
Tests starten
Nach der Installation via pip (`pip install pytest`) oder durch den Paketmanager seiner Wahl kann Pytest grundsätzlich auf zwei Arten gestartet werden:
- mit dem Dateinamen als Argument: `pytest foo.py`
- ohne Argument. In diesem Fall sucht Pytest alle Dateien mit dem Format *\*\_test.py* oder *test\_\*.py* und testet diese
Output
Bei erfolgreichem Test erhält man eine Übersicht über das Test-Resultat:
>======= test session starts =======
platform linux -- Python 3.5.2, pytest-3.0.5, py-1.4.31, pluggy-0.4.0
rootdir: /home/sh/pytest_blog, inifile:
plugins: factoryboy-1.1.6
collected 1 items
first.py .
>======= 1 passed in 0.00 seconds =======
Pytest entfaltet seine Stärke jedoch erst so richtig mit Tests, die nicht funktionieren, indem nach Möglichkeit eine detaillierte Ausgabe gemacht wird, was genau nicht bestanden hat. Sehr schön am Beispiel von zwei Listen, die nicht die selben Elemente enthalten:
def test_list():
>assert [1, 2] == [1, 2, 3]
Resultiert in
def test_list():
> assert [1, 2] == [1, 2, 3]
E assert [1, 2] == [1, 2, 3]
E Right contains more items, first extra item: 3
E Use -v to get the full diff
list.py:4: AssertionError
=============== 1 failed in 0.01 seconds ================
Wie man sieht, liefert Pytest gleich das Element, welches den Fehler verursacht!
Wichtige Optionen
Einige wichtige Optionen von Pytest, die wesentlich beim Gebrauch von Pytest helfen, sind die folgenden:
- `-s` Verhindert das Capturing von Input/Output. Sehr wichtig, da man den Output seiner Print-Statements im normalen Modus nicht sieht oder der Debugger ansonsten nicht gestartet werden kann
- `-k <string>` Dient zum Filtern von Tests. Startet dabei nur diejenigen Tests, die `string` als Substring enthalten
- `-x` Bricht beim ersten fehlgeschlagenen Test ab
Über die Datei pytest.ini können Standardwerte für Pytest konfiguriert werden.
Fixtures
Oftmals benötigen Tests irgendwelche Ressourcen, die zum Testen zur Verfügung stehen müssen. Beispiele hierfür sind Datenbankverbindungen, Config-Files, der Browser für UI-Tests etc. Pytest bietet dafür das Konzept von Fixtures. Man kann sich Fixtures ein wenig wie die `setUp()`- und `tearDown()`-Funktionen von bekannten Unit-Test-Frameworks vorstellen. Jedoch können Pytest-Fixtures viel dynamischer pro Test geladen werden: um eine Fixture in einem Test zu verweden, kann sie lediglich als Argument in der Funktion angegeben werden:
def test_something_fancy(browser):
browser.visit(foo) # browser ist nun eine geladene fixture für diesen test
Um eine Fixture zu erstellen, wird der Decorator `@pytest.fixture` verwendet. Der benötigte Wert wird mit `yield` zurückgegeben. So ist es möglich, dass nach dem yield-Statement die Fixture wieder abgebaut werden kann. Ein Beispiel zur Klärung:
1 import os
2 import sqlite3
3
4 import pytest
5
6 @pytest.fixture(scope='function')
7 def db(tmpdir):
8 file = os.path.join(tmpdir.strpath, "test.db")
9
10 conn = sqlite3.connect(file)
11 conn.execute("CREATE TABLE blog (id, title, text)")
12
13 yield conn
14
15 conn.close()
16
17 def test_entry_creation(db):
18 query = ("INSERT INTO blog "
19 "(id, title, text)"
20 "VALUES (?, ?, ?)")
21 values = (1,
22 "PyTest",
23 "Dies ist ein Blogeintrag")
24
25 db.execute(query, values)
Die Fixture stellt hier eine DB-Verbindung für den Test zur Verfügung und erstellt auch gleich eine Tabelle, die zum Testen nötig ist.
Interessant sind Zeilen 6 und 7: Auf Zeile 6 wird mittels Parameter `scope` festgelegt, wie häufig eine Fixture ausgeführt wird. Zur Verfügung stehen `function`, `class`, `module` und `session`. Wählt man z.B. den Scope `module`, wird die Fixture für das gesamte Modul nur einmal erstellt und anschliessend für jeden Test wiederverwendet. Dies ist sehr praktisch bei Ressourcen, die nicht unbedingt bei jedem Test neu erstellt werden müssen und somit wiederverwendet werden können.
Auf Zeile 7 wird eine weitere Fixture in unserer Fixture geladen, was ohne weiteres möglich ist. In Falle dieses Beispiels ist dies eine Fixture, die von Pytest [mitgeliefert wird](http://docs.pytest.org/en/latest/builtin.html#builtin-fixtures-function-arguments). Sie gibt ein temporäres Verzeichnis zurück das für jeden Test-Aufruf einzigartig ist.
Weitere wichtige Features
Tests parametrisieren
Mit dem Decorator `pytest.mark.parametrize` kann man Tests mit verschiedenen Parametern generieren. Für ein Beispiel erweitern wir den `test_entry_creation` Test von oben:
@pytest.mark.parametrize("id,title,text", [
(1, "House Stark", "Winter is coming"),
(2, "House Lannister", "Hear me Roar"),
(3, "House Martell", "Unbowed, Unbent, Unbroken")
])
def test_parametrized_entry_creation(id, title, text, db):
query = ("INSERT INTO blog "
"(id, title, text)"
"VALUES (?, ?, ?)")
values = (id, title, text)
db.execute(query, values)
So werden nun drei Tests generieren, jeder mit einem anderen Set von Parametern.
Skippen, failen und markieren
Tests können auf verschiedene Arten markiert werden:
- `@pytest.mark.skip(reason=”Not implemented yet”)` bringt Pytest dazu, den Test zu überspringen
- `@pytest.mark.skipif(not os.environ.get(‘CI’, False))` bringt Pytest dazu, den Test zu überpspringen, wenn die Bedingung erfüllt ist
- `@pytest.mark.xfail(reason=”Can’t work yet”)` erwartet, dass ein Test scheitert
- `@pytest.mark.abc` sonstiger Marker. Tests können so beim Aufruf gefiltert werden. Beispiel: starte alle Tests, die mit abc markiert sind: `pytest -m abc`. Um alle Tests zu starten, die *nicht* mit abc markiert sind, kann der `not` Operator benutzt werden: `pytest -m ‘not abc’`
Exceptions erwarten
Wenn Exceptions aus dem getesteten Code erwartet werden, wird dies in Pytest mit einem `ContextManager` gemacht:
def test_exception():
with pytest.raises(Exception):
raise(Exception)
Autouse von Fixtures
Zu guter Letzt, um eine Fixture automatisch in jedem Test zur Verfügung zu stellen, kann dies als Parameter im Decorator übergeben werden. Folgender Code könnte ein Beispiel dafür sein, dass bei jedem Test im Browser ein Login geschieht:@pytest.fixture(autouse=True)
def session(login_page, browser):
login_page.login()
yield
browser.delete_all_cookies()
Zu guter Letzt…
Für Pytest existieren zum Zeitpunkt von diesem Beitrag etwas über 260 Plugins. Sie erweitern Pytest um jenste Sachen, von witzigen Erweiterungen wie das emoji Plugin, welches die Test-Ausgabe etwas spassiger macht, über erweiterte Checks wie Import-Reihenfolge (Isort) und Syntax Linting mit Flake8, zu Erweiterungen wie die Integration von Selenium oder Splinter. Wem also ein Feature in Pytest fehlt, sollte definitiv ein Blick in die Plugin-Liste werfen – es lohnt sich!
Alles in allem, Pytest macht das Testen so einfach, dass es keine Ausreden für das Vernachlässigen von Tests gibt!