Γιατί γράφω τεστ τελευταία, και γιατί δεν είναι αυτό που νομίζεις ότι σημαίνει
**Διαφωνική λήψη:**Test-Driven Development είναι μια λαμπρή πρακτική που λύνει το λάθος πρόβλημα για την πιο δημιουργική εργασία.
Οι τρεις φάσεις του λογισμικού οικοδόμησης (Αυτό λειτουργεί πραγματικά)
Έτσι φτιάχνω λογισμικό.
Είναι απλό, είναι αποτελεσματικό, και κάνει το TDD να καθαρίζει ευγενικά τα φρύδια τους:
Κάνε το να δουλέψει.*Κάνε το όμορφο.*Κλείδωσέ το με εξετάσεις.
graph TB
Start[New Feature Request] --> P1[Phase 1: Make It Work]
P1 --> P1_Private[Private Exploration]
P1_Private --> P1_Sketch["Sketch the solution<br/>Messy code OK<br/>No tests yet<br/>Focus on learning"]
P1_Sketch --> P1_Run["Run it manually<br/>Try different inputs<br/>See what breaks<br/>Understand the problem"]
P1_Run --> P1_Decision{Does it work<br/>basically?}
P1_Decision -->|No| P1_Iterate[Try different approach]
P1_Iterate --> P1_Sketch
P1_Decision -->|Yes| P2
P2[Phase 2: Make It Pretty] --> P2_Refine[Private Refinement]
P2_Refine --> P2_Clean["Clean up the code<br/>Better names<br/>Type hints/annotations<br/>Clear structure"]
P2_Clean --> P2_Align["Align with spec<br/>Cover all requirements<br/>Handle edge cases<br/>Polish API surface"]
P2_Align --> P2_Optimise["Optimise<br/>Performance<br/>Readability<br/>Maintainability"]
P2_Optimise --> P3
P3[Phase 3: Lock It Down] --> P3_Share[Public Sharing]
P3_Share --> P3_Tests["Write comprehensive tests<br/>Full coverage<br/>Edge cases<br/>Error conditions"]
P3_Tests --> P3_CI["CI/CD Integration<br/>Automated testing<br/>Code review<br/>Documentation"]
P3_CI --> P3_Deploy["Ready to Share<br/>Commit to main<br/>Deploy to prod<br/>Other devs can use it"]
P3_Deploy --> Done[Well-Tested,<br/>Well-Designed Code]
style P1 stroke:#ff6b6b,stroke-width:3px
style P2 stroke:#4ecdc4,stroke-width:3px
style P3 stroke:#95e1d3,stroke-width:3px
style Done stroke:#38ada9,stroke-width:4px
Με αυτή τη σειρά.*Πάντα.*Όχι επειδή είμαι τεμπέλης.
Όχι επειδή δεν εκτιμώ τις δοκιμές.
Αυτό είναι το πώς δημιουργική εργασία πραγματικά συμβαίνει
Όταν εξερευνάς έναν προβληματικό χώρο δεν καταλαβαίνεις πλήρως ακόμα.
Όταν εξερευνάς έναν προβληματικό χώρο δεν καταλαβαίνεις πλήρως ακόμα.
Άσε με να σου εξηγήσω.
Αυτό είναι το βρώμικο κομμάτι.Το σημείο που δεν έχω ιδέα τι κάνω.
Προσπαθώ να καταλάβω:
Αυτό το API λειτουργεί πραγματικά με τον τρόπο που ισχυρίζονται οι γιατροί;
Μπορώ να λύσω αυτό το πρόβλημα με τα εργαλεία που έχω;
Τι σημαίνει το "σωστό" σε αυτό το πλαίσιο;*Αυτό είναι ένα πρόβλημα δύο ωρών ή ένα πρόβλημα δύο εβδομάδων;*Αυτό είναι εφεύρεση.
Αυτό είναι εξερεύνηση.
Αυτό είναι τζαζ.
# Ugly, exploratory code
def process_thing(data):
# TODO: This is terrible, fix later
result = []
for item in data:
# Not sure if this is the right approach...
x = item.get('value')
if x: # Is this even the right condition?
result.append(x * 2) # Why multiply by 2? Testing something...
return result
Και ξέρεις τι σκοτώνει την τζαζ;**Κάποιος που στέκεται πάνω από τον ώμο σου λέει "Γράψε πρώτα το τεστ."**Γιατί Δεν Υπάρχουν Δοκιμασίες Ακόμη;
Επειδή*Το σχήμα είναι ακόμα υγρό.*Φαντάσου ότι είσαι γλύπτης.
Έχεις ένα κομμάτι μάρμαρο και μια αόριστη ιδέα: "Θέλω να χαράξω ένα πουλί."
Ορίστε το άνοιγμα των φτερών του.Καθορίστε τη γωνία κάθε φτερού.
Τώρα χαράξτε αυτές τις προδιαγραφές."*Δεν είναι έτσι τα πουλιά σκαλίζονται. (Ή το λογισμικό γράφεται, όπως αποδεικνύεται.)*Αληθινοί γλύπτες
Πρώτα θα κάνω πρόχειρη τη φόρμα.Σχεδίαζαν.
Φτιάχνουν μακέτες.*Κλέβουν μεγάλα κομμάτια πέτρας για να βρουν το γενικό σχήμα.*Μόνο αργότερα καθαρίζουν τις λεπτομέρειες.
Ο κώδικας είναι ο ίδιος.
Αυτός ο κώδικας είναι
Στρατιώτη.
Είναι μια συζήτηση με τον εαυτό μου.
Έτσι καταλαβαίνω τι σημαίνει "δουλεύω."
ενεργά επιβλαβής.
Γιατί κάθε φορά που συνειδητοποιώ ότι "περίμενε, όλη αυτή η προσέγγιση είναι λάθος," θα πρέπει να ξαναγράψω και τα τεστ.
Αυτό δεν είναι ακαμψία.
Η Ελευθερία να Αποτύχουν Γρήγορα
# Before (Phase 1) - Exploratory code
def process_thing(data):
result = []
for item in data:
x = item.get('value')
if x:
result.append(x * 2)
return result
# After (Phase 2) - Refined code
def extract_doubled_values(items: list[dict]) -> list[int]:
"""Extract 'value' field from items and double each one.
Only includes items where 'value' is present and truthy.
"""
return [
item['value'] * 2
for item in items
if item.get('value')
]
Η 1η φάση είναι περίπου
// Before (Phase 1) - Exploratory code
public List<int> ProcessThing(List<Dictionary<string, object>> data)
{
var result = new List<int>();
foreach (var item in data)
{
if (item.ContainsKey("value"))
{
var x = item["value"];
if (x != null)
{
result.Add(Convert.ToInt32(x) * 2);
}
}
}
return result;
}
// After (Phase 2) - Refined code
/// <summary>
/// Extracts 'value' field from items and doubles each one.
/// Only includes items where 'value' is present and non-null.
/// </summary>
public IEnumerable<int> ExtractDoubledValues(IEnumerable<IDictionary<string, object>> items)
{
return items
.Where(item => item.ContainsKey("value") && item["value"] != null)
.Select(item => Convert.ToInt32(item["value"]) * 2);
}
Μαθαίνοντας ταχύτητα.
Πρέπει να ανακαλύψω ότι η βιβλιοθήκη τρίτων που σκέφτηκα να χρησιμοποιήσω... δεν είναι τόσο διαφημισμένη.*Πρέπει να καταλάβω ότι το πρόβλημα που λύνω δεν είναι το πρόβλημα.θα πρέπειΝα λύνουμε.*Οι εξετάσεις επιβραδύνουν αυτό.
Όχι επειδή οι δοκιμές είναι αργές, αλλά επειδή
Τότε έχω επενδύσει συναισθηματικά σε λάθος πράγματα.
Καλύτερα να αποτύχουμε γρήγορα, κατ' ιδίαν, χωρίς δοκιμές για να διατηρήσουμε και κανένα εγωισμό για να προστατεύσουμε.Τι σημαίνει "εργασία" στη Φάση 1Σημαίνει: "Το έλεγξα.
Του έδωσα κάποιες πληροφορίες.
# Phase 1: Works, but awkward to use
process_thing(data)
# Phase 2: Clear, flexible, composable
extract_doubled_values(
items,
scale_factor=2.0,
include_zeros=False
)
Παρήγαγε εξόδους που φαίνονται λογικές.
// Phase 1: Works, but awkward to use
ProcessThing(data);
// Phase 2: Clear, flexible, composable
ExtractDoubledValues(
items,
scaleFactor: 2.0,
includeZeros: false
);
// Or even better with a fluent API
items.ExtractValues()
.Scale(by: 2.0)
.ExcludingZeros()
.ToList();
Είμαι 60% σίγουρος ότι καταλαβαίνω το πρόβλημα τώρα."
Αυτό είναι.**Δεν υπάρχουν ακραίες περιπτώσεις.**Κανένας χειρισμός λάθους.
graph LR
subgraph "Phase 2 Refinement Process"
A[Rough Code] --> B[Clean Structure]
B --> C[Add Types]
C --> D[Polish API]
D --> E[Static Analysis]
E --> F{Quality Gates Pass?}
F -->|No| G[Fix Issues]
G --> B
F -->|Yes| H[Ready for Phase 3]
end
style A stroke:#ff6b6b,stroke-width:3px
style H stroke:#95e1d3,stroke-width:3px
*Απλά μια καρφίτσα.*Μια απόδειξη της έννοιας.
Ένα σκίτσο.Φάση 2: Κάντε το όμορφο (Ο Αποκλεισμός)
Εντάξει, τώρα καταλαβαίνω το πρόβλημα.Έχω κάτι που λειτουργεί, τουλάχιστον για το ευτυχισμένο μονοπάτι.
Τώρα μπορώ να αρχίσω να νοιάζομαι για την ποιότητα.
Παράδειγμα Python:*C# Παράδειγμα:*Καλύτερο όνομα.
Τύπος σημειώσεων.*Τεκμηρίωση XML.*Καθαρότερη εφαρμογή LINQ.
Ευθυγράμμιση με το Spec
Τώρα που ξέρω τι πραγματικά χτίζω, επιστρέφω στις αρχικές απαιτήσεις και βεβαιώνομαι ότι θα λύσω το πρόβλημα.
Δεξιά
αΠρόβλημα.
Συχνά αυτό αποκαλύπτει κενά:
"Ω, ήθελαν αυτό να χειριστεί τους αρνητικούς αριθμούς διαφορετικά."
εμπειρία.**Python:**Γ#:
Καλύτερα να ονομάσουμε.
Γιατί Ακόμη Δεν Υπάρχουν Δοκιμές;
def test_extract_doubled_values_basic():
items = [{'value': 5}, {'value': 10}]
assert extract_doubled_values(items) == [10, 20]
def test_extract_doubled_values_skips_missing_values():
items = [{'value': 5}, {'name': 'foo'}, {'value': 3}]
assert extract_doubled_values(items) == [10, 6]
def test_extract_doubled_values_handles_zeros():
items = [{'value': 0}, {'value': 5}]
# By default, zeros are excluded (falsy)
assert extract_doubled_values(items) == [10]
def test_extract_doubled_values_includes_zeros_when_configured():
items = [{'value': 0}, {'value': 5}]
assert extract_doubled_values(items, include_zeros=True) == [0, 10]
def test_extract_doubled_values_custom_scale_factor():
items = [{'value': 5}]
assert extract_doubled_values(items, scale_factor=3.0) == [15.0]
def test_extract_doubled_values_rejects_negative_scale_factor():
with pytest.raises(ValueError):
extract_doubled_values([], scale_factor=-1.0)
def test_extract_doubled_values_handles_empty_list():
assert extract_doubled_values([]) == []
def test_extract_doubled_values_handles_non_numeric_values():
items = [{'value': 'not a number'}]
with pytest.raises(TypeError):
extract_doubled_values(items)
Το κάνω συνέχεια.
Έχω ανοιχτή μια αναφορά.
Επειδή
# This comment will drift from reality:
# Doubles all numeric values, skipping None
# This test will fail if reality changes:
def test_extract_doubled_values_skips_none_values():
items = [{'value': None}, {'value': 5}]
assert extract_doubled_values(items) == [10]
Ακόμα ανακαλύπτω τι αξίζει να δοκιμάσουμε.
Στη Φάση 1, δεν ήξερα αν αυτή η λειτουργία θα υπήρχε καν.Στη Φάση 2, ανακαλύπτω:"Ο συντελεστής κλίμακας δεν μπορεί να είναι αρνητικός.
"Αν η λίστα είναι άδεια, πρέπει να επιστρέψουμε άδειοι, όχι Κανένας.""Πρέπει να χειριστούμε τις μη αριθμημένες αξίες με χάρη."
Αυτές οι ιδέες
βγαίνει από την αναπαράσταση.
Δεν είναι προφανείς.
Ο κώδικας είναι καθαρός.*Το API βγάζει νόημα.*Έχω καλύψει τις ακραίες περιπτώσεις.
Τώρα γράφω τεστ.
Πολλές εξετάσεις.
Κοντά σε πλήρη κάλυψη, όπως είναι δυνατόν.Γιατί τώρα;
Επειδή
Οι δοκιμές είναι ένας μηχανισμός ανταλλαγής.Δεν είναι πια για μένα.
Καταλαβαίνω ήδη αυτόν τον κώδικα.
Ο αγωγός CI
(η οποία πρέπει να αποτρέψει οπισθοδρόμηση)
Μελλοντικοί Συντηρητές
Δοκιμασίες είναι ηστρώμα παρουσίασης
για την εφαρμογή μου.Καταγράφουν:
Τι κάνει αυτός ο κώδικαςΠοιες είναι έγκυρες οι εισροέςΤι αποτελέσματα να περιμένετε
Τι υποθέσεις κάνω;
Πλήρης κάλυψη, χωρίς συμβιβασμούς
Τροποποίηση αυτής της λειτουργίας με αυτοπεποίθηση
Δοκιμές ως τεκμηρίωση
εκτελέσιμα έγγραφα.
graph TB
subgraph "Traditional TDD (Red-Green-Refactor)"
TDD1[Write Failing Test] --> TDD2[Write Minimal Code to Pass]
TDD2 --> TDD3[Refactor]
TDD3 --> TDD1
end
subgraph "Three-Phase Approach (Explore-Refine-Lock)"
P1[Explore Solution Space] --> P2[Refine Implementation]
P2 --> P3[Write Comprehensive Tests]
P3 --> P4[Share With Team]
end
style TDD1 stroke:#ffaa00,stroke-width:2px
style TDD2 stroke:#ffaa00,stroke-width:2px
style TDD3 stroke:#ffaa00,stroke-width:2px
style P1 stroke:#ff6b6b,stroke-width:3px
style P2 stroke:#4ecdc4,stroke-width:3px
style P3 stroke:#95e1d3,stroke-width:3px
**Αλλά επίσης δεν γράφω τεστ πριν ο κώδικας είναι έτοιμος να μοιραστεί.**Οι φάσεις είναι:
Ιδιωτική εξερεύνηση(μόνο εγώ, δεν δοκιμές)
Ιδιωτική βελτίωση
(μόνο εγώ, ακόμα δεν δοκιμές) |-----|-------------| Κοινή χρήση του κοινού (Δοκιμές, CI, αναθεώρηση κώδικα, όλα τα εννέα μέτρα) Αυτό προστατεύει και τις δύο δημιουργίες μουκαι | Η λογική των συμμαθητών μου. Γιατί Αυτό Προστατεύει τη Δημιουργικότητα
Σωστά!Αλλά μόνο αν ξέρεις ήδη τι φτιάχνεις.
Όταν είμαι στη Φάση 1, δεν χρειάζομαι αυτοπεποίθηση για να αντιληφθώ.
Hour 1: Write test for API I haven't designed yet
Hour 2: Realize the API is wrong, rewrite test
Hour 3: Discover a better approach, rewrite both
Hour 4: Finally get it working
Hour 5: Rewrite tests to match what actually works
Χρειάζομαι άδεια να τα πετάξω όλα.
Hour 1: Explore 3 different APIs, settle on the best one
Hour 2: Refine the implementation, handle edge cases
Hour 3: Write comprehensive tests for what I built
Hour 4: All tests pass, commit with confidence
Οι εξετάσεις δημιουργούν ψυχολογικό χρέος.
Ακόμα κι αν δοκιμάζουν λάθος πράγματα.Αναβάλλοντας τις δοκιμές μέχρι τη Φάση 3, κρατάω τη Φάση 1 και 2
ψυχολογικά φτηνά.
Μπορώ:
Ανακαλύψτε το πρόβλημα είμαιΣτην πραγματικότηταεπίλυση
Έτσι λειτουργεί η δημιουργικότητα.
// Test 1: Write test first (but I don't know the right API yet)
[Test]
public void TestProcessData()
{
var processor = new DataProcessor();
var result = processor.Process(new[] { 1, 2, 3 });
Assert.That(result, Is.EqualTo(new[] { 2, 4, 6 }));
}
// Implementation 1: Make it pass
public class DataProcessor
{
public int[] Process(int[] data) => data.Select(x => x * 2).ToArray();
}
// Later: Realize I need configurability, rewrite test
[Test]
public void TestProcessDataWithFactor()
{
var processor = new DataProcessor();
var result = processor.Process(new[] { 1, 2, 3 }, factor: 3);
Assert.That(result, Is.EqualTo(new[] { 3, 6, 9 }));
}
// Later: Realize I should use IEnumerable, rewrite test again
[Test]
public void TestProcessDataEnumerable()
{
var processor = new DataProcessor();
var data = GetLargeDataset(); // This should be lazy
var result = processor.Process(data, factor: 3);
Assert.That(result.Take(3), Is.EqualTo(new[] { 3, 6, 9 }));
}
Εσύ σκίτσο χαλαρά πρώτα.
Δεν ξεκινάς με τις λεπτομέρειες.
// Phase 1: Explore (no tests yet)
public int[] ProcessThing(int[] data)
{
return data.Select(x => x * 2).ToArray();
}
// Try it: var result = ProcessThing(new[] { 1, 2, 3 });
// Hmm, what about configurability? What about lazy evaluation?
// Phase 2: Refine (still no tests)
public static class DataProcessorExtensions
{
public static IEnumerable<int> Scale(
this IEnumerable<int> source,
int factor = 2)
{
return source.Select(x => x * factor);
}
}
// Try it: var result = data.Scale(factor: 3).ToList();
// Much better API!
// Phase 3: Lock it down (NOW write tests, correctly)
[TestFixture]
public class DataProcessorTests
{
[Test]
public void Scale_DefaultFactor_DoublesValues()
{
var result = new[] { 1, 2, 3 }.Scale();
Assert.That(result, Is.EqualTo(new[] { 2, 4, 6 }));
}
[Test]
public void Scale_CustomFactor_ScalesCorrectly()
{
var result = new[] { 1, 2, 3 }.Scale(factor: 3);
Assert.That(result, Is.EqualTo(new[] { 3, 6, 9 }));
}
[Test]
public void Scale_LazyEvaluation_DoesNotEnumerateImmediately()
{
var enumerated = false;
var data = GetTestData(() => enumerated = true);
var scaled = data.Scale(factor: 2);
Assert.That(enumerated, Is.False, "Should not enumerate yet");
scaled.ToList();
Assert.That(enumerated, Is.True, "Should enumerate on materialization");
}
[Test]
public void Scale_EmptySequence_ReturnsEmpty()
{
var result = Enumerable.Empty<int>().Scale();
Assert.That(result, Is.Empty);
}
}
Πώς Ταιριάζει αυτό με την Αγαθότητα και το XP (Και πού Αναδύεται)
Αυτό δεν είναι "δοκιμάστε αργότερα ανάπτυξη."
Αυτό είναι
η προσθήκη δοκιμών μονάδας είναι κρίσιμης σημασίας.
Οι πρακτικές XP που κρατάω
Κάθε χαρακτηριστικό περνάει από το CI πριν από τη συγχώνευση
Η συνεργατική βελτίωση βελτιώνει το σχεδιασμόΑπλή σχεδίαση
Η φάση 2 είναι
Αναπροσανατολισμός
Η Φάση 2 είναι αφιερωμένος χρόνος αναπαράστασηςΚαθαρίστε τον κωδικόπριν
**Οι δοκιμές προστατεύουν τον αναπαραγωγό (στη Φάση 3+)**Πού Ξεφεύγω από την Αυστηρή TDD
Το TDD λέει:"Πρώτα οι εξετάσεις.
Πάντα.Red-Green-Refactor είναι ο μόνος τρόπος."
Λέω:"Δοκιμάζει όταν ξέρεις τι τεστ κάνεις.
Εξερευνήστε-Refine-Lock είναι πιο φυσικό."
Τρεις-Φάζες Τρεις-ΦάζεςΗ δοκιμή καθορίζει τη διεπαφή ~ Εξερεύνηση ορίζει τη διεπαφή ~
Δοκιμάστε πρώτα για όλα Δοκιμάστε την κατάλληλη στιγμή για κάθε πράγμα
Σωστός συγχρονισμός (Φάση 3):
Ίδιο αποτέλεσμα ποιότητας.*Το μισό χτύπημα.*Αυτό είναι Αγκιλείο.
"Απάντησε να αλλάξεις, ακολουθώντας ένα σχέδιο."Το TDD μπορεί να γίνει η δική του μορφή σχεδίου που ακολουθεί.
Μόλις γράψεις εξετάσεις, είσαι ψυχολογικά αφοσιωμένος σε αυτό το σχέδιο.
Αυτό είναιΠερισσότερα
Αντιθέσεις: ένα παράδειγμα C#
Πρόσεξες το χτύπημα;
Τρεις δοκιμές ξαναγράφτηκαν καθώς εξελίχθηκε το σχέδιο.
Θυμηθείτε τις τιμές:
Η Φάση 1 φτάνει στο λογισμικό εργασίας
Γρήγορα.
Συνεργαστείτε όταν βοηθά (Φάση 2-3), εξερευνήστε μόνοι όταν δεν το κάνει (Φάση 1)
Η φάση 2 ευθυγραμμίζεται με το spec
μετά
Επειδή:
Δεν ήξερες ακόμα τις ακραίες υποθέσεις.Ανακαλύψατε έναν καλύτερο σχεδιασμό APIΣυνειδητοποιήσατε ότι το χαρακτηριστικό δεν ήταν απαραίτητο.
Κάθε τεστ που γράφεις στη Φάση 1 είναι μάλλον χαμένη προσπάθεια.
μία
Σετ δοκιμών στη Φάση 3, όταν ξέρεις τι φτιάχνεις, από το να ξαναγράψεις κατά τη διάρκεια της εξερεύνησης.Υπόσχεση TDD εναντίον ΠραγματικότηταςΤο TDD υπόσχεται:
"Write code that solves the specification.
Don't worry about perfection yet.
Just get it working."
"Οι δοκιμές οδηγούν το σχέδιό σου!
Τώρα ξαναγράφω τις εξετάσεις και τον κώδικα."**Αυτό δεν είναι σχέδιο.**Αυτό είναι
thrushing.Η προσέγγισή μου:
Σχεδιάστε μέσω της εφαρμογής, στη συνέχεια κλειδώστε το κάτω με δοκιμές.
"Όχι δοκιμές"*"Σπρώξε και προσευχήσου"*Μέχρι να τελειώσω με τη Φάση 3, ο κώδικας μου έχει:
Πλήρης κάλυψη των δοκιμώνΥpiοθέσει εκpiοpiή εpiιχειρήσεω
Καθαρισμός σχεδιασμού APIΤεκμηρίωση (μέσω δοκιμών)
Ακριβώς το ίδιο με το TDD.
Η διαφορά είναι
Ο κανόνας είναι απλός:
- flake8 (style checking)
- pylint (code quality)
- mypy (type checking)
- black (formatting)
- radon (complexity analysis)
**Κανένας κωδικός δεν φεύγει από τη Φάση 2 χωρίς τη Φάση 3.**Δεν ξέρω.
for iteration in range(3):
# Measure current performance
metrics = measure_performance(code)
# Generate improved version
better_code = optimise(code, metrics)
# Keep if better, discard if worse
if better_code.score > code.score:
code = better_code
Μη δοκιμασμένη έκδοση κωδικούΆνοιγμα δημοσίων σχέσεων χωρίς δοκιμέςΣυγχώνευση στο κύριο χωρίς περαστικό CI
Δεν είναι καινούρια ιδέα.Έτσι δούλευε πάντα η δημιουργική δουλειά:
Οι ζωγράφοι δεν ξεκινούν με τις τελευταίες πινελιές.*Αυτοί:*ΣκίτςCity name (optional, probably does not need a translation)η σύνθεση (Φάση 1)
Χρώμα*τα στρώματα (Φάση 2)*ΒαρνίςCity name (optional, probably does not need a translation)
# Test generation happens AFTER optimisation
def generate_unit_tests(specification, optimized_code):
"""Generate comprehensive tests for refined code.
This happens in Phase 3, after we know:
- What the code actually does
- What edge cases exist
- What the API surface looks like
"""
return llm.generate(
f"""Generate comprehensive unit tests for this code.
Specification: {specification}
Implementation: {optimized_code}
Include tests for:
- Happy path (from spec examples)
- Edge cases (discovered during optimisation)
- Error conditions (based on actual error handling)
- Performance bounds (based on measured metrics)
"""
)
για την προστασία και την παρουσία (Φάση 3)
Αυτοί:Σχέδιομπερδεμένα (Φάση 1)
**για αντοχή (Φάση 3)**Το γλάσο είναι κρίσιμο.
Πώς αυτό Χάρτες για τον αγωγό DiSE CodegenΕδώ είναι που γίνεται ενδιαφέρον: Έχω πραγματικάσε εφαρμογή
Αυτή η φιλοσοφία στο σύστημα DiSE (Directed Synthetic Evolution).
Γεννήτρια
Καμία πρόωρη βελτιστοποίηση
Δοκιμάστε ξανά με μεγαλύτερη δημιουργικότητα (υψηλότερη θερμοκρασία)
User: "Calculate fibonacci numbers"
[Phase 1: Exploration - 3 attempts]
Attempt 1: Works for small inputs, explodes on large ones (no safety limit)
Attempt 2: Adds safety limit, but inefficient recursive approach
Attempt 3: Switches to iterative DP (PASS)
[Phase 2: Optimization - 3 iterations]
Iteration 1: Add type hints, improve naming (Score: 1.05)
Iteration 2: Optimize memory usage with generator (Score: 1.10)
Iteration 3: Add input validation (Score: 1.15)
[Phase 3: Testing and Storage]
Generated 8 unit tests covering:
- Basic cases (n=0, n=1, n=5, n=10)
- Edge cases (n=negative, n=100, n=None)
- Type validation
All tests pass ✓
Stored in RAG with quality score: 1.15
Available for reuse: YES
Σκαρφαλώστε σε ένα πιο ισχυρό μοντέλο
*Ακριβώς.*Φάση 1.
Δεν υπάρχουν δοκιμές που να γράφονται κατά τη διάρκεια αυτής της φάσης.Ο κώδικας είναι ιδιωτικός στη διαδικασία παραγωγής.
Φάση 2 στο DiSE: Το Στάδιο ΒελτιστοποίησηςΜόλις ο κώδικας περάσει τη βασική εκτέλεση, DiSE κινείται σεΒελτιστοποίηση.
(3 λειτουργίες εξ ορισμού)
Αυτό είναιΑκριβώς.
Ο κωδικός είναι ακόμα ιδιωτικός (όχι ακόμα στο μητρώο), αλλά τον γυαλίζουμε:Καλύτερα ονόματα
Υποδείξεις τύπουΚαθαρότερη δομή
Χαμηλότερη πολυπλοκότητα
Καλύτερη απόδοσηΤο σχήμα δεν είναι πλέον υγρό.
Ξέρουμε τι φτιάχνουμε.
Επίσημες δοκιμές μονάδας.
Οι δοκιμές καλύπτουν:*Παραδείγματα προδιαγραφών (διορθότητα)*Περιστασιακές περιπτώσεις που ανακαλύφθηκαν κατά τη Φάση 2
Χαρακτηριστικά επιδόσεων που έχουν μετρηθείΤότεμόνο εάν περάσουν οι δοκιμές
, ο κωδικός είναι:
RAG μνήμης@ title: window
# I know what sort() should do. Tests first? Sure!
def test_sort_empty_list():
assert sort([]) == []
def test_sort_single_element():
assert sort([5]) == [5]
def test_sort_multiple_elements():
assert sort([3, 1, 2]) == [1, 2, 3]
Προστέθηκε στηνμητρώο κόμβουName:
Στο μέλλον, οι ροές εργασίας
βαθμολογίες ποιότητας
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.