writing unit tests with spock framework
Γράφοντας μονάδες δοκιμών με Spock Framework: Test Fixtures, Assertions and Reporting
Σε αυτό Πλήρης οδηγός για αρχάριους στο Spock , ένα σύντομο Εισαγωγή στον προγραμματισμό Spock Framework και Groovy δόθηκε στο προηγούμενο σεμινάριό μας.
Σε αυτό το σεμινάριο, θα εξετάσουμε όλες τις λεπτομέρειες / βήματα που απαιτούνται για να ξεκινήσετε Δοκιμή μονάδας στο Σποκ.
Για λόγους απλότητας, πρόκειται να δοκιμάσουμε μια απλή εφαρμογή αριθμομηχανής η οποία έχει διαφορετικές μεθόδους όπως προσθήκη, αφαίρεση, πολλαπλασιασμό, διαίρεση κ.λπ., όλες οι οποίες δέχονται ακέραιες παραμέτρους και επιστρέφουν ακέραια έξοδο.
Τι θα μάθετε:
- Δοκιμή μονάδας με Spock Video Tutorial
- Ξεκινώντας
- Λέξη-κλειδί «def»
- Ο κύκλος ζωής μιας προδιαγραφής Spock
- Επιβεβαιώσεις Spock
- Αναφορά
- συμπέρασμα
- Συνιστώμενη ανάγνωση
Δοκιμή μονάδας με Spock Video Tutorial
Ξεκινώντας
Παρόμοιο με οποιοδήποτε άλλο πλαίσιο δοκιμών μονάδας, το Spock μπορεί επίσης να χρησιμοποιηθεί για τη σύνταξη σεναρίων / δοκιμαστικών περιπτώσεων για μια υπό δοκιμή εφαρμογή. Θα προσπαθήσουμε να συγκρίνουμε και να συγκρίνουμε τα διαφορετικά χαρακτηριστικά του πλαισίου Spock με τα υπάρχοντα / γνωστά πλαίσια όπως JUnit .
Λέξη-κλειδί «def»
Ας προσπαθήσουμε πρώτα να κατανοήσουμε εν συντομία τη λέξη-κλειδί «def» του Groovy. Η λέξη-κλειδί def χρησιμοποιείται για τον ορισμό του τύπου-def και μπορεί να χρησιμοποιηθεί για να δηλώσει μια συνάρτηση καθώς και ένα πεδίο / μεταβλητή.
Το 'def' χρησιμοποιείται γενικά όταν δεν θέλουμε να περιορίσουμε τον τύπο πεδίου ή τον τύπο επιστροφής μιας μεθόδου. Ας δούμε μερικά παραδείγματα def λέξεων-κλειδιών σε μια κατηγορία groovy και όλες τις έγκυρες χρήσεις της.
// def as variable types def inputNum = 100 def inputStr = 'hello world!!' def app = new CalculatorApp() // def as return type of function def 'test function'() { // function body here }
Ο κύκλος ζωής μιας προδιαγραφής Spock
Το Spock spec κατά την εκτέλεση αναζητά όλες τις δοκιμές που ορίζονται και τις εκτελεί μία προς μία. Ωστόσο, υπάρχουν λίγες άλλες λειτουργίες / δυνατότητες που παρέχονται από το Spock για να κάνουν τις δοκιμές λιγότερο περιττές και πιο ευανάγνωστες.
Ας συζητήσουμε μερικά χαρακτηριστικά παρακάτω:
Ορισμός εισόδων / μεταβλητών ως μέρος του Spec
Εξετάστε το ενδεχόμενο να κάνετε πολλές δοκιμές όλες χρησιμοποιώντας τις ίδιες τιμές εισαγωγής. Ένας τρόπος θα ήταν να αρχικοποιήσουμε τις τιμές εισόδου σε κάθε δοκιμή ξεχωριστά, αλλιώς μπορούμε να ορίσουμε άμεσα τα πεδία σε επίπεδο προδιαγραφών και να διασφαλίσουμε ότι πριν από κάθε δοκιμή, τα πεδία θα αρχικοποιηθούν και θα είναι διαθέσιμα στη δοκιμή που εκτελείται.
Ας δούμε ένα παράδειγμα για την τάξη εφαρμογής της αριθμομηχανής .
Θα καθορίσουμε τα δεδομένα εισόδου σε επίπεδο προδιαγραφών έτσι ώστε να είναι διαθέσιμα με τις αρχικές τιμές σε όλες τις δοκιμές που υπάρχουν στην προδιαγραφή.
class CalculatorAppSpec extends Specification { def input1 = 50 def input2 = 10 def result = 0 def app = new CalculatorApp() def 'addition with valid inputs return expected result'() { when: result = app.add(input1, input2) then: result == 60 } def 'multiplication with valid inputs return expected result'() { when: result = app.multiply(input1, input2) then: result == 500 } def 'division with valid inputs return expected result'() { when: result = app.divide(input1, input2) then: result == 5 } def 'subsctraction with valid inputs return expected result'() { when: result = app.substract(input1, input2) then: result == 40 } }
Σε αυτό το δείγμα κώδικα, μπορείτε να δείτε, ότι έχουμε ορίσει input1, input2, την υπό δοκιμή εφαρμογή και αποτέλεσμα σε επίπεδο προδιαγραφών. Αυτό που διασφαλίζει είναι ότι κάθε φορά που εκτελείται μια δοκιμή από τα αρχεία προδιαγραφών και τα αρχικοποιημένα πεδία περνούν σε αυτήν τη δοκιμή. Αυτό εξαλείφει πράγματι την ανάγκη για ρύθμιση δοκιμών κάθε φορά με τιμές εισόδου.
Φωτιστικά δοκιμής
Παρόμοια με τα περισσότερα πλαίσια δοκιμής μονάδας, το Spock παρέχει επίσης μεθόδους εγκατάστασης και εκκαθάρισης για την εκτέλεση ειδικής λογικής / εργασιών σε συγκεκριμένα συμβάντα κύκλου ζωής εκτέλεσης δοκιμής.
setupSpec & cleanupSpec
Αυτές οι μέθοδοι καλούνται μία φορά για κάθε εκτέλεση Spec και καλούνται πριν και μετά την εκτέλεση δοκιμής αντίστοιχα. Αυτά είναι συγκρίσιμα με το @ Πριν το μάθημα και @ Μετά το μάθημα σχολιασμοί του JUnit.
εγκατάσταση & καθαρισμός
Αυτές οι μέθοδοι καλούνται πριν και μετά την εκτέλεση κάθε δοκιμής στις προδιαγραφές.
Αυτά τα άγκιστρα είναι το σωστό μέρος για οποιαδήποτε λογική / κομμάτι κώδικα που θέλετε να εκτελέσετε πριν και μετά την εκτέλεση της δοκιμής. Για παράδειγμα Κατά την εκκαθάριση, μπορείτε να γράψετε έναν κωδικό για να κλείσετε τη σύνδεση βάσης δεδομένων (εάν υπάρχει) που χρησιμοποιήθηκε κατά τη διάρκεια της δοκιμής.
Αυτά μπορούν να συγκριθούν με @ Πριν από τη δοκιμή και @ Μετά από δοκιμή σχολιασμοί στο JUnit.
Ας δούμε ένα παράδειγμα αυτών των φωτιστικών στη δοκιμή εφαρμογής της αριθμομηχανής.
def setupSpec() { println('###in setup spec!') } def cleanupSpec() { println('###in cleanup spec!') } def setup() { println('>>>in test setup!') } def cleanup() { println('>>>in test cleanup!') }
Αν ο παραπάνω κωδικός δοκιμής προστίθεται σε μια προδιαγραφή που περιέχει 4 δοκιμές, τότε η έξοδος θα είναι όπως παρακάτω:
###in setup spec! >>>in test setup! >>>in test cleanup! >>>in test setup! >>>in test cleanup! >>>in test setup! >>>in test cleanup! >>>in test setup! >>>in test cleanup! ###in cleanup spec!
Επιβεβαιώσεις Spock
Οι ισχυρισμοί στο Spock ονομάζονται power assert (και υιοθετήθηκε από τον groovy αργότερα μετά την εισαγωγή του από τον Spock). Οι ισχυρισμοί Spock παρέχουν πολλές διαγνωστικές εξαιρέσεις σε περίπτωση τυχόν αστοχίας ισχυρισμού.
Κάποιος μπορεί εύκολα να ανακαλύψει τι πήγε στραβά κοιτάζοντας απλώς τη διάγνωση αστοχίας σε αντίθεση με τη ρήξη Σφάλματα Assertion στο JUnit και σε άλλα πλαίσια.
Ας προσπαθήσουμε να το κατανοήσουμε με ένα παράδειγμα και να το αντιπαραθέσουμε με το JUnit
Θα εργαστούμε με μια απλή δοκιμή που ελέγχει την ισότητα των συμβολοσειρών και θα δούμε τι διαγνωστικά δημιουργούνται σε περίπτωση αποτυχίας ισχυρισμού.
Δοκιμή Spock
def 'check case-insensitive equality of 2 strings'() { given: 'two input strings' String str1 = 'hello' String str2 = 'HELLO world' when: 'strings are lowercased' str1 = str1.toLowerCase() str2 = str2.toLowerCase() then: 'equal strings should return success' str1 == str2 }
Δοκιμή JUnit
δείγματα περιπτώσεων δοκιμής σε δοκιμές λογισμικού
@Test public void compareStrings_withValidInput_shouldReturnSuccess() { // Arrange String str1 = 'hello'; String str2 = 'HELLO world'; // Act str1 = str1.toLowerCase(); str2 = str2.toLowerCase(); // Assert Assert.assertEquals(str1,str2); }
Έξοδος Spock
Condition not satisfied: str1 == str2 | | | hello| hello world false 6 differences (45% similarity) hello(------) hello( world) Expected :hello world Actual :hello
Έξοδος JUnit
org.junit.ComparisonFailure: Expected :hello Actual :hello world
Όπως μπορείτε να συμπεράνετε από ψηλά, οι πληροφορίες διάγνωσης που παρέχονται από το Spock έχουν καλύτερες λεπτομέρειες και είναι πιο φιλικές προς το χρήστη σε σύγκριση με τα άλλα πλαίσια όπως το JUnit.
Συμβουλές και κόλπα ισχυρισμού
Επιβεβαίωση πολλαπλών στοιχείων ταυτόχρονα - Το Spock παρέχει διάφορες συντομεύσεις για ισχυρισμούς και ένα τέτοιο είναι η σημείωση '*' που επιτρέπει την επιβεβαίωση των στοιχείων στη λίστα.
Ας το καταλάβουμε με ένα παράδειγμα:
Σκεφτείτε μια κλάση CityInfo που έχει το όνομα πόλης και τον πληθυσμό ως πεδία. Θα γράψουμε ένα τεστ Spock για να επιβεβαιώσουμε τα ονόματα των πόλεων που υπάρχουν στη συγκεκριμένη λίστα.
public class CityInfo { public CityInfo(String cityName, int population) { this.cityName = cityName; this.population = population; } public String cityName; public int population; }
Ας δούμε τη δοκιμή τώρα:
def 'Assert multiple elements of list' () { given: def cityList = new LinkedList() cityList.add(new CityInfo('Mumbai', 120)) cityList.add(new CityInfo('Delhi', 80)) cityList.add(new CityInfo('Chennai', 100)) expect: cityList*.cityName == ('Mumbai', 'Delhi', 'Chennai') }
Όπως φαίνεται στην παραπάνω περιγραφή, θα μπορούσατε να επικυρώσετε ολόκληρη τη λίστα με τη βοήθεια της λέξης-κλειδιού «*».
Ας δούμε επίσης πώς θα ήταν μια αποτυχία. Θα καταργήσω το όνομα οποιασδήποτε πόλης από τον παραπάνω ισχυρισμό.
Condition not satisfied: cityList*.cityName == ('Delhi', 'Chennai') | | | | | false | (Mumbai, Delhi, Chennai) (app.CityInfo@31368b99, app.CityInfo@1725dc0f, app.CityInfo@3911c2a7)
Μπορείτε να δείτε ότι οι διαγνωστικές πληροφορίες σχετικά με την αποτυχία ισχυρισμού είναι πλούσιες και κατανοητές.
Αξιοποίηση της παραμέτρου κλεισίματος - κάθε ().
Ας δούμε, πώς μπορούμε να αξιοποιήσουμε την παράμετρο κλεισίματος που ονομάζεται κάθε () για να προσθέσουμε μια δήλωση για κάθε στοιχείο μιας λίστας ή συλλογής. Στο ίδιο παράδειγμα, ας προσπαθήσουμε να προσθέσουμε έναν ισχυρισμό που επικυρώνει τον πληθυσμό κάθε πόλης εάν η δεδομένη είσοδος είναι> 50.
def 'Assert multiple elements of list' () { given: def cityList = new LinkedList() cityList.add(new CityInfo('Mumbai', 120)) cityList.add(new CityInfo('Delhi', 80)) cityList.add(new CityInfo('Chennai', 100)) expect: cityList*.cityName == ('Mumbai', 'Delhi', 'Chennai') and: cityList.population.every() { it > 50 } }
Ισχυρισμός εξαιρέσεων από ρίψη
Εξαιρέσεις μπορούν να υποστηριχθούν ότι ρίχνονται στο μπλοκ «τότε» (που σημαίνει a όταν απαιτείται επίσης το μπλοκ). Η λεπτομέρεια εξαίρεσης μπορεί να διαγνωστεί με την ανάθεση της εξαιρούμενης εξαίρεσης σε ένα πεδίο και με την επιβεβαίωση των απαιτούμενων ιδιοτήτων της εξαίρεσης που ρίχνεται.
Ας χρησιμοποιήσουμε την ίδια κλάση CityInfo και ορίστε μια μέθοδο που ρίχνει μια εξαίρεση και γράψτε μια δοκιμή για αυτήν.
public class CityInfo { public CityInfo(String cityName, int population) { this.cityName = cityName; this.population = population; } public String cityName; public int population; public CityInfo() { } public int getCleanlinessScore() { throw new RuntimeException('method not implemented'); } }
Ας δούμε τώρα το τεστ:
def 'cleanliness score throws runtime exception with message - method not implemented'() { given: CityInfo app = new CityInfo(); when: app.cleanlinessScore() then: def e = thrown(RuntimeException) e.message == 'method not implemented' }
Αναφορά
Προκειμένου να δημιουργηθούν όμορφες και λεπτομερείς αναφορές βασισμένες σε HTML, υπάρχουν διαθέσιμες βιβλιοθήκες που μπορούν να προστεθούν στο αρχείο build και τώρα κάθε φορά που οι δοκιμές εκτελούνται κατά τη διάρκεια της έκδοσης (ή με άμεση εκτέλεση), θα δημιουργηθεί μια λεπτομερής αναφορά βάσει HTML φάκελος εξόδου.
Για να δημιουργήσετε τις δοκιμαστικές αναφορές, προσθέστε τις ακόλουθες βιβλιοθήκες στο αρχείο build.gradle (και παρόμοια και για το αρχείο Maven pom.xml).
testCompile 'com.athaydes:spock-reports:1.6.1' testCompile 'org.slf4j:slf4j-api:1.7.13' testCompile 'org.slf4j:slf4j-simple:1.7.13'
Τώρα δημιουργήστε το έργο και εκτελέστε τις δοκιμές εκτελώντας όλες τις δοκιμές στο φάκελο 'test' ή εκτελώντας ' βαθμολογήστε καθαρό τεστ '.
Μπορείτε να ανοίξετε index.html αρχείο για να λάβετε μια συνοπτική αναφορά για όλες τις προδιαγραφές Spock που ήταν διαθέσιμες για εκτέλεση.
Εάν θέλετε να δείτε τη λεπτομερή αναφορά για μια συγκεκριμένη προδιαγραφή, κάντε κλικ στην προδιαγραφή από την παραπάνω λίστα και μπορείτε να δείτε μια λεπτομερή αναφορά αποτυχιών καθώς και επιτυχιών.
συμπέρασμα
Σε αυτό το σεμινάριο, καλύψαμε τα βασικά της δοκιμής μονάδας με το Spock Framework. Είδαμε τους διαφορετικούς τρόπους και συντομογραφίες για τη σύνταξη ισχυρισμών και το είδος των πλούσιων πληροφοριών διάγνωσης που δημιουργήθηκαν από το πλαίσιο Spock για αποτυχίες διεκδίκησης.
Εξετάσαμε επίσης τον τρόπο με τον οποίο θα μπορούσαμε να δημιουργήσουμε ήσυχες αναφορές βασισμένες σε HTML για τις δοκιμές Spock που περιλαμβάνουν τα ίδια λεπτομερή διαγνωστικά για τις δοκιμές που εκτελέστηκαν.
Το επερχόμενο σεμινάριό μας θα σας ενημερώσει σχετικά με τη σύνταξη παραμετροποιημένων δοκιμών με το Spock λεπτομερώς !!
Εκπαιδευτικό πρόγραμμα PREV | ΕΠΟΜΕΝΟ Φροντιστήριο
Συνιστώμενη ανάγνωση
- Με βάση δεδομένα ή παραμετρικές δοκιμές με πλαίσιο Spock
- Ερωτήσεις συνέντευξης Spock με απαντήσεις (πιο δημοφιλείς)
- Spock για ενσωμάτωση και λειτουργική δοκιμή με σελήνιο
- Spock Mocking and Stubbing (Παραδείγματα με Video Tutorials)
- Tutorial Spock: Δοκιμή με Spock και Groovy
- Εκπαιδευτικό Mockito: Mockito Framework για χλευασμό σε δοκιμές μονάδας
- Οι διαφορές μεταξύ δοκιμών μονάδας, δοκιμής ολοκλήρωσης και δοκιμής λειτουργίας
- Κλειδί για επιτυχημένη δοκιμή μονάδας - Πώς δοκιμάζουν οι προγραμματιστές τον δικό τους κώδικα;