Given-When-Then — είναι ένα δομικό πρότυπο για την περιγραφή σεναρίων δοκιμών, το οποίο δανείστηκε η BDD από το domain-driven design και προσαρμόστηκε για το Behaviour-Driven Development. Η μορφή χωρίζει το σενάριο σε τρία λογικά μέρη: προϋποθέσεις (Given), ενέργεια (When) και αναμενόμενο αποτέλεσμα (Then). Σύμφωνα με τον Martin Fowler (2023), το Given-When-Then δεν είναι απλώς μια μορφή δοκιμών, αλλά ένα εργαλείο σκέψης που πειθαρχεί την ανάλυση απαιτήσεων και τη σχεδίαση σεναρίων πριν από την έναρξη της υλοποίησης.
Κύρια σημεία
Given-When-Then — είναι ένα πρότυπο περιγραφής συμπεριφοράς, που διατυπώθηκε για πρώτη φορά από τον Dan North το 2006 ως μέρος της μεθοδολογίας Behavior-Driven Development. Το πρότυπο λύνει το πρόβλημα των μη δομημένων περιγραφών σεναρίων δοκιμών, που συχνά περιέχουν ένα μείγμα προϋποθέσεων, ενεργειών και ελέγχων σε αυθαίρετη σειρά.
Η βασική ιδέα του προτύπου είναι ο διαχωρισμός ευθυνών μεταξύ των τριών μπλοκ. Κάθε μπλοκ είναι υπεύθυνο για ακριβώς μία πτυχή του σεναρίου: την κατάσταση πριν, το συμβάν κατά τη διάρκεια και τον έλεγχο μετά. Αυτό κάνει το σενάριο αναγνώσιμο, επαληθεύσιμο και αυτοματοποιήσιμο. Σύμφωνα με έρευνα προγραμματιστών του πλαισίου Cucumber (2024), τα σενάρια που ακολουθούν αυστηρά το πρότυπο Given-When-Then απαιτούν 42% λιγότερο χρόνο για κατανόηση από ένα νέο μέλος της ομάδας.
Ο Dan North δανείστηκε την ιδέα της τριμερούς δομής από τη formulation of tests στο TDD και τη μεθοδολογία Test-by-Example (που δημιουργήθηκε από τον Brian Marick). Ο Marick πρότεινε την περιγραφή απαιτήσεων μέσω παραδειγμάτων (examples) που ταυτόχρονα χρησιμεύουν ως δοκιμές. Το Given-When-Then επισημοποίησε αυτή την ιδέα, μετατρέποντας μη δομημένα παραδείγματα σε επαναλαμβανόμενο πρότυπο.
Το πρότυπο Given-When-Then εφαρμόζεται όχι μόνο σε σενάρια BDD στο Gherkin, αλλά και σε συνηθισμένες μοναδιαίες δοκιμές σε JUnit, XCTest και άλλα πλαίσια. Τα σχόλια στον κώδικα που χωρίζουν τη δοκιμή σε τρία μπλοκ είναι μια διαδεδομένη πρακτική για τη βελτίωση της αναγνωσιμότητας της βάσης δοκιμών. Η Google προτείνει αυτή την προσέγγιση στο βιβλίο της “Software Engineering at Google” (2020).
Κάθε μπλοκ Given-When-Then έχει αυστηρά καθορισμένη σημασιολογία και κανόνες συμπλήρωσης. Η παραβίαση αυτών των κανόνων οδηγεί σε σενάρια που είναι δύσκολο να αυτοματοποιηθούν ή να γίνουν κατανοητά.
Το μπλοκ Given περιγράφει την κατάσταση του συστήματος πριν από την εκτέλεση της δοκιμαζόμενης ενέργειας. Περιλαμβάνει: υπάρχοντα αντικείμενα (χρήστης, παραγγελία, ρυθμίσεις), ενεργές καταστάσεις (εξουσιοδοτημένος, συνδεδεμένος στο δίκτυο), καθώς και αρχικές τιμές δεδομένων. Κάθε Given πρέπει να είναι επαληθεύσιμο — εάν η κατάσταση του συστήματος δεν αντιστοιχεί στο Given, το σενάριο πρέπει να παραλειφθεί ή το περιβάλλον δοκιμής να προετοιμαστεί εκ των προτέρων.
Το μπλοκ When περιγράφει το μοναδικό συμβάν που ξεκινά τη δοκιμαζόμενη συμπεριφορά. Αυτό μπορεί να είναι η κλήση μιας μεθόδου, το πάτημα ενός κουμπιού, η λήψη μιας ειδοποίησης ή απάντησης από τον διακομιστή. Ο βασικός κανόνας — ένα When ανά σενάριο. Εάν πρέπει να ελεγχθεί μια ακολουθία ενεργειών, δημιουργούνται ξεχωριστά σενάρια, όχι μια αλυσίδα When.
// Given: δημιουργούμε δεδομένα δοκιμής
val user = User(email = "test@example.com", balance = 500.0)
val product = Product(price = 150.0)
// When: εκτελούμε την ενέργεια
val result = PurchaseUseCase().buy(user, product)
// Then: ελέγχουμε το αποτέλεσμα
assertEquals(PurchaseResult.Success, result)
assertEquals(350.0, user.balance)
Το μπλοκ Then ελέγχει εάν το σύστημα έχει μεταβεί στην αναμενόμενη κατάσταση. Αυτό περιλαμβάνει: επιστρεφόμενες τιμές, αλλαγές κατάστασης αντικειμένων, κλήσεις εξωτερικών υπηρεσιών (μέσω επαλήθευσης mock), καθώς και αλλαγές UI. Κάθε μπλοκ Then μπορεί να περιέχει πολλούς ελέγχους, αλλά όλοι αναφέρονται σε μία ενέργεια.
Given-When-Then και Arrange-Act-Assert (AAA) — είναι δύο παραλλαγές του ίδιου τριμερούς προτύπου, αλλά με διαφορετικό κοινό-στόχο. Η κατανόηση των διαφορών τους βοηθά στην επιλογή της σωστής μορφής για μια συγκεκριμένη εργασία.
| Πτυχή | Given-When-Then | Arrange-Act-Assert |
|---|---|---|
| Προέλευση | BDD, επιχειρηματική ανάλυση | Μοναδιαία δοκιμή |
| Γλώσσα | Φυσική (Gherkin) | Κώδικας (Kotlin, Swift, Java) |
| Κοινό | Ολόκληρη η ομάδα + πελάτης | Προγραμματιστές |
| Επίπεδο λεπτομέρειας | Υψηλού επιπέδου | Λεπτομερές |
| Αυτοματοποίηση | Cucumber, SpecFlow | JUnit, XCTest, Mockito |
Το πρότυπο Given-When-Then είναι βέλτιστο για σενάρια που συζητούνται με τον πελάτη ή τον αναλυτή: κριτήρια αποδοχής λειτουργιών, σενάρια χρήσης, έλεγχοι παλινδρόμησης. Η σύνταξη Gherkin επιτρέπει τη συγγραφή τέτοιων σεναρίων χωρίς γνώση προγραμματισμού.
Arrange-Act-Assert — είναι η φυσική επιλογή για μοναδιαίες δοκιμές που ελέγχουν μια συγκεκριμένη μέθοδο ή κλάση. Η μορφή AAA δεν απαιτεί πρόσθετα πλαίσια και λειτουργεί σε οποιαδήποτε γλώσσα προγραμματισμού. Για ανάπτυξη iOS, η Apple προτείνει το AAA στην τεκμηρίωση XCTest (2024).
Ας δούμε πρακτικά παραδείγματα Given-When-Then σε Kotlin για μια εφαρμογή Android. Το πρώτο παράδειγμα — δοκιμή καλαθιού αγορών χρησιμοποιώντας MockK. Το δεύτερο — δοκιμή λογικής push ειδοποιήσεων.
class CartTest {
fun `apply discount when total exceeds threshold`() {
// Given
val cart = Cart()
cart.addItem(Item("Laptop", price = 1000.0))
cart.addItem(Item("Mouse", price = 50.0))
val discount = DiscountCalculator(0.1)
// When
val total = discount.applyIfEligible(cart)
// Then
assertEquals(945.0, total)
assertTrue("Discount was not applied", total < 1050.0)
}
}
Το δεύτερο παράδειγμα δείχνει το Given-When-Then με ασύγχρονο κώδικα. Εδώ το Given ορίζει την κατάσταση του Firebase Cloud Messaging, το When — τη λήψη push ειδοποίησης, το Then — τον έλεγχο επεξεργασίας.
class PushNotificationTest {
fun `handle push notification when app in background`() = runTest {
// Given
val prefs = mockk<SharedPreferences>()
every { prefs.getString("token", null) } returns "fcm-token-abc"
val handler = PushHandler(prefs)
// When
val data = RemoteMessage().apply {
putData("type", "order_update")
putData("order_id", "123")
}
val result = handler.handleNotification(data)
// Then
assertEquals(NotificationAction.OpenOrder("123"), result)
}
}
Το τρίτο παράδειγμα — ένα σενάριο BDD σε Gherkin, που δείχνει το Given-When-Then στο πλαίσιο δοκιμών αποδοχής:
Feature: User Authorization
Scenario: User cannot login with expired token
Given the user has an expired refresh token
When they try to access the protected profile screen
Then they should see the login screen
And the app should clear all cached data
Η αποτελεσματική χρήση του Given-When-Then απαιτεί τήρηση αρκετών δοκιμασμένων πρακτικών. Αυτές εξασφαλίζουν την αναγνωσιμότητα, τη συντηρησιμότητα και την αυτοματοποιησιμότητα των σεναρίων.
Αυστηρός κανόνας: ένα σενάριο — μία ενέργεια. Εάν πρέπει να ελεγχθεί μια ακολουθία πολλαπλών When, δημιουργήστε πολλαπλά σενάρια, όπου το αποτέλεσμα του προηγούμενου γίνεται προϋπόθεση του επόμενου. Αυτό κάνει το σενάριο ατομικό και κατανοητό.
Το Given πρέπει να περιγράφει την ουσία, όχι συγκεκριμένους αριθμούς. Αντί για “Given ο χρήστης Ιβάνοφ με υπόλοιπο 500 ρούβλια” — “Given χρήστης με επαρκές υπόλοιπο”. Τα συγκεκριμένα δεδομένα μεταφέρονται στο Scenario Outline με τον πίνακα Examples. Αυτό κάνει το σενάριο καθολικό και επαναχρησιμοποιήσιμο.
Η ενσωμάτωση σεναρίων Given-When-Then στον αγωγό συνεχούς ολοκλήρωσης τα μετατρέπει από τεκμηρίωση σε προστασία από παλινδρομήσεις. Κάθε αίτημα συγχώνευσης σε ένα κινητό έργο εκκινεί αυτόματα σενάρια BDD και αποκλείει τη συγχώνευση εάν αποτύχει τουλάχιστον ένα σενάριο.
Τα σενάρια BDD σε Cucumber για Android εκκινούνται μέσω εργασίας Gradle ./gradlew cucumber. Για iOS (Quick/Nimble) — μέσω xcodebuild test. Σε συστήματα CI (GitHub Actions, GitLab CI, Bitrise) οι δοκιμές BDD εκτελούνται σε εξομοιωτές ή πραγματικές συσκευές. Η αναφορά δημιουργείται σε μορφή HTML, κατανοητή από διαχειριστές: πράσινα σενάρια — επιτυχία, κόκκινα — αποτυχία με ένδειξη του βήματος.
Τα αρχεία .feature αποθηκεύονται στο αποθετήριο δίπλα στον κώδικα και υπόκεινται σε code review. Ο αναλυτής δημιουργεί αίτημα συγχώνευσης με νέα σενάρια πριν από την έναρξη της ανάπτυξης (BDD-first). Ο προγραμματιστής γράφει step definitions και υλοποίηση για να γίνουν αυτά τα σενάρια πράσινα. Όταν όλα τα σενάρια περνούν — η λειτουργικότητα είναι έτοιμη. Αυτή η προσέγγιση, που περιγράφεται στο βιβλίο του Gojko Adzic “Specification by Example” (2011), μετατρέπει τις απαιτήσεις σε εκτελέσιμο τεχνούργημα.
Συχνές ερωτήσεις
Ως προς τη δομή — ναι, είναι το ίδιο τριμερές πρότυπο. Η διαφορά είναι στο κοινό: το Given-When-Then είναι προσανατολισμένο σε επιχειρηματική γλώσσα και χρησιμοποιείται σε BDD με Gherkin, ενώ το Arrange-Act-Assert είναι μια τεχνική μορφή για μοναδιαίες δοκιμές. Η επιλογή εξαρτάται από το πλαίσιο και την ομάδα.
Δεν υπάρχουν περιορισμοί, αλλά συνιστάται όχι περισσότεροι από 3–5 έλεγχοι ανά Then. Εάν υπάρχουν περισσότεροι έλεγχοι, το σενάριο πιθανώς ελέγχει πάρα πολλά σε μία ενέργεια. Χωρίστε το σε πολλαπλά σενάρια με διαφορετικά Then.
Όχι. Το πρότυπο μπορεί να χρησιμοποιηθεί σε οποιοδήποτε πλαίσιο δοκιμών, απλά διαιρώντας τη δοκιμή με σχόλια ή κενές γραμμές σε τρία μπλοκ. Το Gherkin χρειάζεται μόνο εάν τα σενάρια γράφονται σε μορφή αρχείου .feature για Cucumber ή SpecFlow.
Συνιστάται η μεταφορά επαναλαμβανόμενων προϋποθέσεων σε Background (Gherkin) ή μεθόδους @Before (JUnit). Εάν οι προϋποθέσεις είναι περίπλοκες, χρησιμοποιήστε το πρότυπο Builder για τη δημιουργία δεδομένων δοκιμής. Αυτό διατηρεί το Given σύντομο και αναγνώσιμο.
Όχι. Το When είναι ένα υποχρεωτικό μπλοκ που περιγράφει την ενέργεια. Εάν το σενάριο ελέγχει μόνο την κατάσταση χωρίς ενέργεια (για παράδειγμα, “κατά τη φόρτωση της εφαρμογής τα δεδομένα πρέπει να αποθηκεύονται στην προσωρινή μνήμη”), το When περιγράφει τον ενεργοποιητή: “όταν η εφαρμογή εκκινείται”.
Περίληψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης