Ich habe festgestellt, dass ein Großteil meiner rechnergestützten Programmierung Testanforderungen hat, die nicht durch Standard-Test-Frameworks abgedeckt sind:
Berechnung der Rechenzeit
- Um sicherzustellen, dass Algorithmen nicht langsamer werden. Ich könnte so etwas tun,
assureSmallerEqual(RuntimeWrapper(algorithm),53)
aber ich möchte, dass der 53-Sekunden-Schwellenwert kontinuierlich reduziert wird, während ich an dem Algorithmus arbeite, dh so etwasassureSmallerEqual(RuntimeWrapper(algorithm),'previousbest+noisetolerance')
- Um sicherzustellen, dass Algorithmen nicht langsamer werden. Ich könnte so etwas tun,
Leistungstest
- Um sicherzustellen, dass ein Algorithmus, der zuvor eine gute Annäherung an eine analytische Lösung gefunden hat, immer noch eine Lösung findet, die mindestens genauso gut oder besser ist. Auch dies könnte durch einen Standard-Integrationstest emuliert werden, aber ich möchte, dass die Toleranz kontinuierlich abnimmt, wenn der Algorithmus immer besser wird. Denken Sie daran,
assureAlmostEqual(foo(),1,places=3)
durch zu ersetzenassureAlmostEqual(foo(),1,places='previousbest')
- Um sicherzustellen, dass ein Algorithmus, der zuvor eine gute Annäherung an eine analytische Lösung gefunden hat, immer noch eine Lösung findet, die mindestens genauso gut oder besser ist. Auch dies könnte durch einen Standard-Integrationstest emuliert werden, aber ich möchte, dass die Toleranz kontinuierlich abnimmt, wenn der Algorithmus immer besser wird. Denken Sie daran,
Prüfung der körperlichen Anforderungen
- Um sicherzustellen, dass Algorithmen nicht plötzlich mehr Speicher / Festplattenspeicher benötigen. Sehr ähnlich zu 1.
Abstrakte Anforderungsprüfung
- Um sicherzustellen, dass ein Algorithmus, der mit quadratischen Approximationen gut funktioniert hat, nicht plötzlich kubische Approximationen benötigt, oder dass ein Algorithmus, der mit Zeitschritt 0.1 gut funktioniert hat, nicht plötzlich 0,01 für Stabilität benötigt. Auch diese könnten durch Standardintegrationstests emuliert werden. Ziel ist es jedoch, sich daran zu erinnern, welcher der kleinsten Anforderungsparameter ein bestimmtes Ziel erreicht hat. Dies würde daher viele manuelle Aktualisierungen erfordern. Wenn zum Beispiel
foo(10)
zuvor keine Ausnahmen geworfen wurden, möchte ich, dass das Framework sicherstellt, dass esfoo(10)
immer noch funktioniert, und auch versucht, ob esfoo(9)
jetzt funktioniert (in diesem Fall würden alle zukünftigen Tests sicherstellen, dass esfoo(9)
immer noch funktioniert).
- Um sicherzustellen, dass ein Algorithmus, der mit quadratischen Approximationen gut funktioniert hat, nicht plötzlich kubische Approximationen benötigt, oder dass ein Algorithmus, der mit Zeitschritt 0.1 gut funktioniert hat, nicht plötzlich 0,01 für Stabilität benötigt. Auch diese könnten durch Standardintegrationstests emuliert werden. Ziel ist es jedoch, sich daran zu erinnern, welcher der kleinsten Anforderungsparameter ein bestimmtes Ziel erreicht hat. Dies würde daher viele manuelle Aktualisierungen erfordern. Wenn zum Beispiel
Man könnte argumentieren, dass das, wonach ich frage, keine Tests im Sinne von Unit- / Integrationstests beschreibt, da beispielsweise längere Laufzeiten als Gegenleistung für andere Verbesserungen akzeptabel sein könnten.
In der Praxis weiß ich jedoch, dass ich viel Debugging-Zeit gespart hätte, wenn ich die oben genannten Testfunktionen gehabt hätte, da in 95% der Fälle Anforderungen und Leistung aufgrund von Fehlern, die ich eingeführt habe, schief gelaufen sind. In der Tat weiß ich, dass viele Fehler, die ich (nach viel Zeitverschwendung beim Überprüfen meines eigenen Codes) mit externen numerischen Softwarebibliotheken gefunden habe, trivial hätten vermieden werden können, wenn die oben genannten Tests rigoros angewendet worden wären.
PS
Die ähnlich benannte Frage /programming/34982863/framework-for-regression-testing-of-numerical-code ist kein Duplikat, da sie Funktionen beschreibt, die mit Standard-Regressionstest-Frameworks leichter zu erreichen sind.
Die Frage Strategien für Unit-Tests und testgetriebene Entwicklung fragt nach Strategien im Gegensatz zu einem Framework, das bei deren Implementierung hilft (und die Strategien, nach denen gefragt wird / die in den Antworten enthalten sind, unterscheiden sich meiner Meinung nach von den hier beschriebenen).
Antworten:
1. Diese Art von Test scheint mir schlecht definiert zu sein, da seine Testbedingung an die bestimmte Maschine gebunden ist, auf der Sie Tests in der Entwicklung durchgeführt haben. Einer der Testpunkte ist, dass das Ausführen Ihrer Tests auf meinem Laptop mir sagt, ob etwas mit dem Code oder der von mir eingerichteten Umgebung nicht stimmt. Die 53 Sekunden sind spezifisch für Ihren Entwicklungscomputer. Die Laufzeit erhöht sich auch, wenn der Testcomputer von anderen Workloads oder Benutzern belastet wird. Ich würde nicht erwarten, dass Test-Frameworks dies beheben: "Funktion läuft bei Eingabe in weniger als 53 Sekunden" ist einfach keine sehr gute Korrektheitsspezifikation.
2. Ich denke, dass dies aus Sicht der Softwaretests aus den gleichen Gründen mehrdeutig und unerwünscht ist. 1 Sie verlieren die Pass-or-Fail-Rechtfertigung für Softwaretests.
3. Dies ist durchaus üblich. Lassen Sie mich eine Lösung beschreiben. Es ist nicht ganz die Aufgabe eines Testframeworks, aber Sie können ein separates Tool verwenden, wie in der Unix SE-Frage beschrieben. Beschränken Sie die Speichernutzung für einen einzelnen Linux-Prozess . Ein Standardwerkzeug , das Sie zuerst ausprobieren sollten, ist der
ulimit
Befehl inbash
, mit dem Sie einen Prozess ausführen und sicherstellen können, dass er abstürzt, wenn versucht wird, z. B. zu viel Speicher zuzuweisen. Wenn Sie dasruntests
Skript mit einem Speicherlimit ausführen , stürzt es ab und das Testframework sollte dies als regulären Testfehler behandeln können.4. Die meist Test - Frameworks nicht denken , Unit - Tests auf diese Weise überhaupt . Die Testsuite wird ausgeführt (z. B. vor dem Festschreiben von Code an den Master oder vor der Bereitstellung), und das Ergebnis ist ein Ja oder Nein, das angibt, ob sie funktioniert. Das Testen von Frameworks betrachtet es nicht als Teil ihrer Aufgabe, z. B. den Fortschritt von Features zu verfolgen, und das ist das Testen im Allgemeinen nicht. Was Sie hier tun würden, wäre, zwei Tests zu schreiben
expect_succeeds(foo(10)); expect_fails(foo(9))
. Jedes Mal werden beide Tests ausgeführt und die Erfolge und erwarteten Fehler bestehen. Wenn Sie implementierenfoo(9)
und es erfolgreich ist, schlägt der Expect-Failure-Test jetzt fehl, sodass Sie ihn neu schreiben würdenexpect_succeeds(foo(9))
, und dies ist ein absolutes Standardmerkmal aller Frameworks. Sie müssen jedoch genau angeben, welches Verhalten Sie erwarten, da es sonst einfach zu sehr gegen die Grundideen des Softwaretests verstößt.performs_better(foo_A(), foo_B())
quelle