JUnit Παραμετροποιημένη δοκιμή με Παράδειγμα χρησιμοποιώντας @Parameters
⚡ Έξυπνη Σύνοψη
Παραμετροποιημένες δοκιμές σε JUnit εκτελέστε την ίδια μέθοδο δοκιμής επανειλημμένα με διαφορετικές τιμές εισόδου, επομένως μία μέθοδος καλύπτει πολλά σενάρια. Οι σχολιασμοί @RunWith και @Parameters παρέχουν το σύνολο δεδομένων για κάθε επανάληψη.
Τι είναι μια παραμετροποιημένη δοκιμή στο JUnit?
A παραμετροποιημένη δοκιμή είναι μια δοκιμή που εκτελεί την ίδια μέθοδο δοκιμής ξανά και ξανά χρησιμοποιώντας διαφορετικές τιμές. Βοηθά τους προγραμματιστές να εξοικονομήσουν χρόνο κατά τη σύνταξη δοκιμών που διαφέρουν μόνο ως προς τα δεδομένα εισόδου και τα αναμενόμενα αποτελέσματα.
Χρησιμοποιώντας μια παραμετροποιημένη δοκιμή, μπορεί κανείς να ρυθμίσει μια μέθοδο δοκιμής που ανακτά δεδομένα από κάποια πηγή δεδομένων. Αυτό την καθιστά την απλούστερη μορφή δοκιμές βάσει δεδομένων διαθέσιμο μέσα JUnit από μόνο του, χωρίς να απαιτείται εξωτερική βιβλιοθήκη.
Σκεφτείτε ένα απλό τεστ που αθροίζει διαφορετικούς αριθμούς. Ο κώδικας μπορεί να μοιάζει με αυτό:
Η παραπάνω προσέγγιση οδηγεί σε μεγάλο πλεονασμό. Κάθε νέο ζεύγος αριθμών χρειάζεται μια άλλη εντολή assert μέσα στην ίδια μέθοδο, και μια αποτυχία στην πρώτη δήλωση αποκρύπτει κάθε δήλωση που την ακολουθεί.
Απαιτείται μια απλούστερη προσέγγιση. Χρησιμοποιώντας μια παραμετροποιημένη δοκιμή, μπορείτε να προσθέσετε μία μόνο μέθοδο που παρέχει δέκα εισόδους δεδομένων και η δοκιμή σας θα εκτελεστεί αυτόματα δέκα φορές.
Βήματα για τη δημιουργία ενός παραμετροποιημένου JUnit Δοκιμή
Ο ακόλουθος κώδικας δείχνει ένα παράδειγμα παραμετροποιημένης δοκιμής. Ελέγχει τη μέθοδο sum() της κλάσης Airthematic, η οποία είναι η ορθογραφία που χρησιμοποιείται σε όλο το δείγμα έργου.
Βήμα 1) Δημιουργήστε μια κλάση. Σε αυτό το παράδειγμα, θα εισαγάγουμε δύο αριθμούς χρησιμοποιώντας τη μέθοδο sum(int, int), η οποία θα επιστρέψει το άθροισμα των δεδομένων αριθμών.
Βήμα 2) Δημιουργήστε μια παραμετροποιημένη κλάση δοκιμής.
Code εξήγηση
- Code Γραμμή 11: Σχολιάστε την κλάση δοκιμής σας χρησιμοποιώντας το @RunWith(Parameterized.class).
- Code Γραμμή 13: Δηλώστε τη μεταβλητή 'firstNumber' ως ιδιωτική και πληκτρολογήστε ως int.
- Code Γραμμή 14: Δηλώνοντας τη μεταβλητή 'secondNumber' ως ιδιωτική και πληκτρολογώντας την ως int.
- Code Γραμμή 15: Δηλώνοντας τη μεταβλητή 'expectedResult' ως ιδιωτική και πληκτρολογώντας την ως int.
- Code Γραμμή 16: Δηλώνοντας τη μεταβλητή 'airthematic' ως ιδιωτική και τον τύπο της ως Airthematic.
@RunWith(class_name.class): το @RunWith Η σχολίαση χρησιμοποιείται για να καθορίσει το όνομα της κλάσης εκτέλεσης. Εάν δεν καθορίσουμε κανέναν τύπο ως παράμετρο, ο χρόνος εκτέλεσης θα επιλέξει ΑποκλεισμόςJUnit4ClassRunner από προεπιλογή.
Αυτή η κλάση είναι υπεύθυνη για τις δοκιμές που θα εκτελεστούν με μια νέα δοκιμαστική παρουσία. Είναι υπεύθυνη για την κλήση JUnit μέθοδοι κύκλου ζωής όπως η εγκατάσταση (πόροι συσχέτισης) και η αποσύνδεση (απελευθέρωση πόρων), οι οποίες περιγράφονται στο JUnit εξάρτημα δοκιμής tutorial.
Για να παραμετροποιήσετε, πρέπει να σχολιάσετε την κλάση χρησιμοποιώντας το @RunWith και να περάσετε την απαιτούμενη .class που θα δοκιμαστεί.
Βήμα 3) Δημιουργήστε έναν κατασκευαστή που αποθηκεύει τα δεδομένα δοκιμής. Αποθηκεύει 3 μεταβλητές.
Βήμα 4) Δημιουργήστε μια στατική μέθοδο που δημιουργεί και επιστρέφει δεδομένα δοκιμής.
Code Γραμμή 32,33: Δημιουργία ενός δισδιάστατου πίνακα (παρέχοντας παραμέτρους εισόδου για πρόσθεση). Χρησιμοποιώντας τη μέθοδο asList μετατρέπουμε τα δεδομένα σε τύπο List, καθώς ο τύπος επιστροφής της μεθόδου εισόδου είναι Collection.
Code Γραμμή 30: Χρήση του @Παράμετροι σχολιασμός για τη δημιουργία ενός συνόλου δεδομένων εισόδου για την εκτέλεση της δοκιμής μας.
Η στατική μέθοδος που προσδιορίζεται από την σχολίαση @Parameters επιστρέφει μια Συλλογή όπου κάθε καταχώρηση στη Συλλογή θα είναι τα δεδομένα εισόδου για μία επανάληψη της δοκιμής. Θεωρήστε το στοιχείο {1,2,3}. Εδώ:
- πρώτοςΑριθμός = 1
- δεύτεροςΑριθμός = 2
- αναμενόμενο αποτέλεσμα = 3
Εδώ, κάθε στοιχείο πίνακα θα διαβιβάζεται στον κατασκευαστή, ένα κάθε φορά, καθώς η κλάση δημιουργείται πολλές φορές. Οι πέντε πίνακες που δηλώνονται στο παράδειγμα παράγουν επομένως τις ακόλουθες πέντε εκτελέσεις:
| Επανάληψη | πρώτοςΑριθμός | δεύτεροςΑριθμός | αναμενόμενο αποτέλεσμα | Γραμμή κονσόλας |
|---|---|---|---|---|
| [0] | 1 | 2 | 3 | Άθροισμα Numbers = : 3 |
| [1] | 11 | 22 | 33 | Άθροισμα Numbers = : 33 |
| [2] | 111 | 222 | 333 | Άθροισμα Numbers = : 333 |
| [3] | 10 | 9 | 19 | Άθροισμα Numbers = : 19 |
| [4] | 100 | 9 | 109 | Άθροισμα Numbers = : 109 |
Βήμα 5) Ο πλήρης κώδικας.
Code Επεξήγηση:
- Code Γραμμή 25: Χρήση της σχολίασης @Before για τη ρύθμιση των πόρων (Airthematic.class εδώ). Η σχολίαση @Before χρησιμοποιείται εδώ για εκτέλεση πριν από κάθε περίπτωση δοκιμής. Περιέχει την προϋπόθεση της δοκιμής.
- Code Γραμμή 36: Χρησιμοποιώντας την σχολίαση @Test για να δημιουργήσουμε τη δοκιμή μας.
- Code Γραμμή 39: Δημιουργία ενός δήλωση διεκδίκησης για να ελέγξουμε αν το άθροισμά μας είναι ισοδύναμο με αυτό που περιμέναμε.
Βήμα 6) Δημιουργήστε μια κλάση εκτέλεσης δοκιμής για να εκτελέσετε την παραμετροποιημένη δοκιμή:
Code Επεξήγηση:
- Code Γραμμή 8: Δηλώνοντας την κύρια μέθοδο της κλάσης Test που θα εκτελέσει την JUnit δοκιμή.
- Code Γραμμή 9: Εκτέλεση δοκιμαστικών περιπτώσεων χρησιμοποιώντας JUnitCore.runClasses, το οποίο λαμβάνει το όνομα της κλάσης δοκιμής ως παράμετρο (στο παράδειγμά μας χρησιμοποιούμε το AirthematicTest.class).
- Code Γραμμή 11: Επεξεργασία του αποτελέσματος χρησιμοποιώντας έναν βρόχο for και εκτύπωση του αποτυχημένου αποτελέσματος.
- Code Γραμμή 13: Εκτύπωση του επιτυχημένου αποτελέσματος.
Παραγωγή:
Εδώ είναι το αποτέλεσμα, το οποίο δείχνει μια επιτυχημένη δοκιμή χωρίς αποτυχία tracε, όπως δίνεται παρακάτω. Σημειώστε ότι το JUnit Η προβολή παραθέτει μία καταχώρηση ανά γραμμή δεδομένων αντί για μία μόνο δοκιμή:
Δείτε το αποτέλεσμα στην κονσόλα, το οποίο δείχνει την πρόσθεση των δύο αριθμών:
Παραμετροποιημένες δοκιμές σε JUnit 5 με @ParameterizedTest
Το παραπάνω παράδειγμα γράφτηκε για JUnit 4. JUnit Το 5 (Δίας) εγκαταλείπει εντελώς το μοντέλο εκτέλεσης, επομένως το @RunWith(Parameterized.class), ο κατασκευαστής δεδομένων και τα πεδία στιγμιοτύπων εξαφανίζονται. JUnit 4 Ο κώδικας που φαίνεται παραπάνω δεν είναι παρωχημένος: εξακολουθεί να εκτελείται αμετάβλητος στο JUnit Πλατφόρμα μέσω της vintage μηχανής. Οι νέες δοκιμές, ωστόσο, συνήθως γράφονται με το @ParameterizedTest.
Απαιτούνται δύο εξαρτήσεις: junit-jupiter-api για τις σχολιασμοί δοκιμών και παράμετροι junit-jupiter για την παραμετροποιημένη υποστήριξη. Χωρίς το δεύτερο τεχνούργημα, οι σχολιασμοί πηγής δεν θα επιλυθούν καθόλου.
import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; class AirthematicTest { // one row per iteration, no constructor and no runner @ParameterizedTest(name = "{0} + {1} = {2}") @CsvSource({"1, 2, 3", "11, 22, 33", "111, 222, 333", "10, 9, 19", "100, 9, 109"}) void sumOfTwoNumbers(int firstNumber, int secondNumber, int expectedResult) { assertEquals(expectedResult, new Airthematic().sum(firstNumber, secondNumber)); } }
Ο Jupiter προσφέρει αρκετές πηγές ορισμάτων και η σωστή εξαρτάται από το σχήμα των δεδομένων:
| Σχολιασμός πηγής | Προμήθειες | Χρησιμοποιήστε το όταν |
|---|---|---|
| @ValueSource | Μία μόνο στήλη με κυριολεκτικά γράμματα | Το τεστ δέχεται ακριβώς ένα όρισμα |
| @CsvSource | Ενσωματωμένες γραμμές διαχωρισμένες με κόμμα | Μικροί πίνακες αριθμών και συμβολοσειρών που διαβάζονται καθαρά στο αρχείο |
| @CsvFileSource | Γραμμές που διαβάζονται από ένα CSV στη διαδρομή κλάσης δοκιμής | Το σύνολο δεδομένων είναι μεγάλο ή διατηρείται εκτός κώδικα |
| @MethodSource | Ένα στατικό εργοστάσιο επιστρέφει μια ροή ορισμάτων | Απαιτούνται πραγματικά αντικείμενα, υπολογισμένες τιμές ή τυχαιοποιημένα δεδομένα |
| @EnumSource | Οι σταθερές μιας απαρίθμησης | Κάθε τιμή απαρίθμησης πρέπει να ασκείται |
Δύο κανόνες ισχύουν για τους περισσότερους αρχάριους. Μια σχολίαση πηγής που τοποθετείται σε μια απλή μέθοδο @Test αγνοείται σιωπηλά, επομένως η μέθοδος πρέπει να φέρει το @ParameterizedTest. Και μια κενή τιμή χωρίς εισαγωγικά στο @CsvSource διαβάζεται ως null, ενώ μια κενή τιμή σε εισαγωγικά διαβάζεται ως κενή συμβολοσειρά.
The JUnit 4 σχολιασμοί που χρησιμοποιούνται σε αυτό το άρθρο αντιστοιχίζονται στον Jupiter ως εξής: Το @RunWith(Parameterized.class) γίνεται @ParameterizedTest συν μια σχολίαση πηγής, το @Parameters γίνεται @MethodSource ή @CsvSource και το @Before γίνεται @BeforeEach. Η πλήρης λίστα καλύπτεται στο JUnit σχολιασμούς tutorial.
Πλεονεκτήματα και περιορισμοί των παραμετροποιημένων δοκιμών
Η παραμετροποίηση δεν είναι δωρεάν. Αφαιρεί τις επικαλύψεις, αλλά περιορίζει επίσης τον τρόπο με τον οποίο μπορεί να γραφτεί μια δοκιμή, επομένως αξίζει να γνωρίζετε και τις δύο πλευρές πριν από τη μετατροπή μιας υπάρχουσας σουίτας.
Πλεονεκτήματα
- Less αναπαραγωγή σε πανομοιότυπο: Μία μέθοδος αντικαθιστά ένα μπλοκ σχεδόν πανομοιότυπων δηλώσεων assert, όπως δείχνει το πρώτο στιγμιότυπο οθόνης σε αυτό το άρθρο.
- Φθηνότερη κάλυψη: Η προσθήκη μιας περίπτωσης edge κοστίζει μία ακόμη γραμμή δεδομένων αντί για μια εντελώς νέα περίπτωση δοκιμής μέθοδος.
- Ακριβής αναφορά: Κάθε επανάληψη αναφέρεται ξεχωριστά, επομένως JUnit Η προβολή προσδιορίζει ακριβώς ποια γραμμή απέτυχε αντί για μία συγκεντρωτική αποτυχία.
- Κεντρικά δεδομένα: Οι είσοδοι αποθηκεύονται σε μία μόνο μέθοδο και μπορούν αργότερα να μετακινηθούν σε ένα αρχείο CSV ή σε ένα εργοστάσιο χωρίς να επηρεαστούν οι ισχυρισμοί.
Περιορισμοί
- Μία μορφή ισχυρισμού: Κάθε γραμμή εκτελεί τους ίδιους ισχυρισμούς, επομένως ένα σενάριο που χρειάζεται διαφορετικούς ελέγχους εξακολουθεί να χρειάζεται τη δική του μέθοδο δοκιμής.
- Πεδίο εφαρμογής σε επίπεδο κλάσης σε JUnit 4: Ο εκτελεστής παραμετροποιεί ολόκληρη την κλάση, επομένως οι άσχετες μέθοδοι @Test σε αυτήν την κλάση εκτελούνται επίσης μία φορά ανά γραμμή.
- Μη αναγνώσιμες αναφορές: Χωρίς πρότυπο ονόματος, οι αποτυχίες εμφανίζονται ως testAirthematicTest[3], το οποίο δεν αναφέρει τίποτα για τα δεδομένα που παρουσίασαν σφάλμα.
- Ογκώδη ενσωματωμένα δεδομένα: Οι μεγάλοι πίνακες παραγκωνίζουν τη λογική δοκιμής. Μετακινήστε τους στο @CsvFileSource ή σε ένα εργοστάσιο @MethodSource.
Συνηθισμένα σφάλματα στο JUnit Παραμετροποιημένες δοκιμές
Οι περισσότερες παραμετροποιημένες αποτυχίες είναι σφάλματα αρχικοποίησης που προκύπτουν πριν από την εκτέλεση μιας μεμονωμένης διεκδίκησης. Ο παρακάτω πίνακας παραθέτει τα μηνύματα που εμφανίζονται πιο συχνά και τι τα ενεργοποιεί.
| Το μήνυμά σας | Αιτία | σταθερός |
|---|---|---|
| Η κλάση δοκιμής θα πρέπει να έχει ακριβώς έναν δημόσιο κατασκευαστή | Η κλάση δηλώνει κανέναν δημόσιο κατασκευαστή, ή δύο από αυτούς | Διατηρήστε έναν δημόσιο κατασκευαστή του οποίου οι παράμετροι ταιριάζουν με τις στήλες δεδομένων |
| Δεν υπάρχει μέθοδος δημόσιων στατικών παραμέτρων στην κλάση | Η μέθοδος @Parameters δεν είναι δημόσια στατική ή επιστρέφει λάθος τύπο | Δηλώστε το ως δημόσια στατική Συλλογή και επιστρέψτε Arrays.asList(…) |
| IllegalArgumentException: λάθος αριθμός ορισμάτων | Μια γραμμή είναι πιο φαρδιά ή πιο στενή από τη λίστα παραμέτρων του κατασκευαστή | Κάντε κάθε πίνακα στη Συλλογή να έχει το ίδιο πλάτος με τον κατασκευαστή |
| Σφάλμα διαμόρφωσης: δεν υπάρχει πάροχος ορισμάτων | Μια δοκιμή Jupiter φέρει το @ParameterizedTest χωρίς σχολιασμό πηγής | Προσθήκη @ValueSource, @CsvSource, @CsvFileSource, @MethodSource ή @EnumSource |
| Η σχολίαση πηγής φαίνεται να μην κάνει τίποτα | Η μέθοδος σχολιάζεται με @Test αντί για @ParameterizedTest | Αντικαταστήστε το @Test με το @ParameterizedTest και εισαγάγετε το junit-jupiter-params |
Μια ακόμη παγίδα είναι η κοινή κατάσταση. Επειδή η κοινή κατάσταση. JUnit δημιουργεί μια νέα παρουσία ανά γραμμή, οτιδήποτε διατηρείται σε ένα στατικό πεδίο επιβιώνει από κάθε επανάληψη και μια τιμή που γράφεται από τη γραμμή [0] μπορεί να αλλάξει αθόρυβα το αποτέλεσμα της γραμμής [4]. Διατηρήστε την κατάσταση ανά γραμμή στα πεδία παρουσίας και επαναφέρετε τους κοινόχρηστους πόρους στη μέθοδο @Before ή @BeforeEach. Γενικές οδηγίες σχετικά με την απομόνωση δοκιμών καλύπτονται στο δοκιμή μονάδας tutorial.









