{"id":464,"date":"2025-05-10T20:28:35","date_gmt":"2025-05-10T20:28:35","guid":{"rendered":"https:\/\/mityjohn.com\/?p=464"},"modified":"2025-05-19T09:29:10","modified_gmt":"2025-05-19T09:29:10","slug":"tdd-is-dead-long-live-the-test","status":"publish","type":"post","link":"https:\/\/mityjohn.com\/?p=464","title":{"rendered":"TDD is Dead. Long Live the Test."},"content":{"rendered":"\n<p><em>Why classic test-driven development doesn\u2019t fit AI-powered coding<\/em><\/p>\n\n\n\n<p>There was a time when <strong>Test-Driven Development (TDD)<\/strong> was treated as a foundational discipline in software engineering. Writing the failing test first, then the minimal implementation, and finally refactoring became the mantra for clean code \u2014 a ritual popularized by Uncle Bob and widely practiced in craftsmanship circles.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"756\" height=\"1000\" src=\"https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image.png\" alt=\"\" class=\"wp-image-465\" style=\"width:226px;height:auto\" srcset=\"https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image.png 756w, https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image-227x300.png 227w\" sizes=\"auto, (max-width: 756px) 100vw, 756px\" \/><\/figure>\n\n\n\n<p>But in the era of <strong>GitHub Copilot<\/strong>, <strong>autonomous coding agents<\/strong>, and <strong>large language model-assisted development<\/strong>, that model no longer fits the way we build software. It\u2019s not that testing is obsolete \u2014 far from it. But the rigid, test-first mindset of TDD has become a mismatch for how AI-enhanced teams operate today.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">From deliberate design to dynamic interaction<\/h3>\n\n\n\n<p>TDD was built for a world where developers crafted every line by hand. It enforced intentionality: design the behavior, write a failing test, then write code to satisfy it. But modern development is increasingly <strong>reactive and iterative<\/strong>. Developers prompt Copilot, tweak generated snippets, and evolve code based on live feedback \u2014 not formal specifications.<\/p>\n\n\n\n<p>In this world, tests often come <strong>after<\/strong> the first working version, generated automatically or written selectively to validate the most critical paths. The idea of pausing to handcraft a test before writing code can feel more like friction than discipline.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Agents change the game<\/h3>\n\n\n\n<p>In systems where <strong>multi-agent architectures<\/strong> write, review, and refactor code collaboratively \u2014 with distinct roles like planner, implementer, reviewer, tester \u2014 the classical TDD cycle doesn\u2019t even make sense. These agents engage in iterative convergence: proposing, analyzing, adapting. The act of manually specifying behavior in test-first style becomes almost redundant when the agents themselves are reasoning toward intent.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/ChatGPT-Image-10-mei-2025-22_24_20.png\" alt=\"\" class=\"wp-image-468\" style=\"width:445px;height:auto\" srcset=\"https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/ChatGPT-Image-10-mei-2025-22_24_20.png 1024w, https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/ChatGPT-Image-10-mei-2025-22_24_20-300x300.png 300w, https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/ChatGPT-Image-10-mei-2025-22_24_20-150x150.png 150w, https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/ChatGPT-Image-10-mei-2025-22_24_20-768x768.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>And with frameworks like <strong>AutoGen<\/strong>, <strong>LangGraph<\/strong>, or <strong>CrewAI<\/strong>, these collaborative agent workflows are already becoming part of real-world toolchains<sup><a class=\"\" href=\"#user-content-fn-1\">1<\/a><\/sup>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Not anti-testing \u2014 just post-dogmatic<\/h3>\n\n\n\n<p>Let\u2019s be clear: <strong>testing remains essential<\/strong>. But it\u2019s time to evolve the mental model. TDD enforces a strict workflow that\u2019s no longer compatible with fluid, AI-assisted development.<\/p>\n\n\n\n<p>Instead of dogma, we need testing strategies that match our tooling:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Post-hoc AI-generated tests<\/strong>, reviewed and enriched by humans<\/li>\n\n\n\n<li><strong>Property-based testing<\/strong>, using tools like <a class=\"\" href=\"https:\/\/hypothesis.readthedocs.io\/\">Hypothesis<\/a> (Python) or <a class=\"\" href=\"https:\/\/jqwik.net\/\">jqwik<\/a> (Java) to validate system behavior over wide input ranges<\/li>\n\n\n\n<li><strong>Observability-first development<\/strong>, leveraging tools like <a class=\"\" href=\"https:\/\/opentelemetry.io\/\">OpenTelemetry<\/a> or <a>Grafana Loki<\/a> to trace runtime behavior instead of relying solely on static tests<\/li>\n\n\n\n<li><strong>Simulation and scenario testing<\/strong>, often orchestrated using platforms like <a class=\"\" href=\"https:\/\/www.testcontainers.org\/\">TestContainers<\/a> or <a class=\"\" href=\"https:\/\/www.cypress.io\/\">Cypress<\/a> for integrated flows<\/li>\n\n\n\n<li><strong>Contract-first testing<\/strong>, especially in API development, using OpenAPI, Pact<sup><a class=\"\" href=\"#user-content-fn-2\">2<\/a><\/sup>, or GraphQL schema validation<\/li>\n<\/ul>\n\n\n\n<div style=\"height:29px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Trust isn\u2019t blind \u2014 it\u2019s built<\/h3>\n\n\n\n<p>In AI-enhanced development, <strong>trust is the new test<\/strong> \u2014 but not in the na\u00efve sense of blind faith in machine output. The core question isn\u2019t just \u201cdoes the code pass tests?\u201d but rather:<br><strong>Do we understand and trust how the code was produced?<\/strong><\/p>\n\n\n\n<p>This trust must be <strong>constructed, measured, and governed<\/strong>. That means:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Traceable pipelines<\/strong>, where code origin (AI or human) is recorded \u2014 e.g., via GitHub\u2019s <strong>Copilot telemetry<\/strong>, or internal annotations in CI\/CD logs<\/li>\n\n\n\n<li><strong>Audit trails<\/strong>, supported by tools like <a class=\"\" href=\"https:\/\/www.traceloop.com\/\">Traceloop<\/a> or <a class=\"\" href=\"https:\/\/www.promptlayer.com\/\">PromptLayer<\/a> to monitor LLM and agent decisions<\/li>\n\n\n\n<li><strong>Mitigation and oversight policies<\/strong>, including AI usage policies (see <a class=\"\" href=\"https:\/\/www.nist.gov\/itl\/ai-risk-management-framework\">NIST AI Risk Management Framework<\/a> or EU AI Act guidelines)<\/li>\n\n\n\n<li><strong>Bias and compliance checks<\/strong>, using frameworks such as <a class=\"\" href=\"https:\/\/trustyai.ai\/\">TrustyAI<\/a> (by Red Hat) to validate fairness, explainability, and correctness in AI-generated logic<\/li>\n\n\n\n<li><strong>Secure design reviews<\/strong>, where agents\u2019 code is verified against threat models, known vulnerability patterns, and business constraints \u2014 ideally automated<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image-3-1024x683.png\" alt=\"\" class=\"wp-image-470\" style=\"width:425px;height:auto\" srcset=\"https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image-3-1024x683.png 1024w, https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image-3-300x200.png 300w, https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image-3-768x512.png 768w, https:\/\/mityjohn.com\/wp-content\/uploads\/2025\/05\/image-3.png 1536w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div style=\"height:32px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">From test-first to trust-first<\/h3>\n\n\n\n<p>TDD was a great discipline for the era of hand-coded logic. But in a world where code is co-authored with machines, and change is continuous, we need <strong>more adaptive validation practices<\/strong> \u2014 not inherited rituals from a pre-AI era.<\/p>\n\n\n\n<p>Trust in AI-assisted systems isn\u2019t automatic. But with the right <strong>governance, tooling, and cultural shifts<\/strong>, it\u2019s entirely possible to build systems we can rely on \u2014 even if they weren\u2019t written line-by-line by a human hand.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-default\"\/>\n\n\n\n<p><strong>Footnotes<\/strong><\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Examples include <a>LangGraph<\/a>, <a>CrewAI<\/a>, and <a>AutoGen<\/a>.<\/li>\n\n\n\n<li>See <a>Pact<\/a> for contract testing in distributed systems.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Why classic test-driven development doesn\u2019t fit AI-powered coding There was a time when Test-Driven Development (TDD) was treated as a foundational discipline in software engineering. Writing the failing test first, then the minimal implementation, and finally refactoring became the mantra for clean code \u2014 a ritual popularized by Uncle Bob and widely practiced in craftsmanship [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":467,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,7],"tags":[19,20,10],"class_list":["post-464","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai","category-development","tag-ai","tag-generative-ai","tag-programming"],"_links":{"self":[{"href":"https:\/\/mityjohn.com\/index.php?rest_route=\/wp\/v2\/posts\/464","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mityjohn.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mityjohn.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mityjohn.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mityjohn.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=464"}],"version-history":[{"count":1,"href":"https:\/\/mityjohn.com\/index.php?rest_route=\/wp\/v2\/posts\/464\/revisions"}],"predecessor-version":[{"id":471,"href":"https:\/\/mityjohn.com\/index.php?rest_route=\/wp\/v2\/posts\/464\/revisions\/471"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mityjohn.com\/index.php?rest_route=\/wp\/v2\/media\/467"}],"wp:attachment":[{"href":"https:\/\/mityjohn.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=464"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mityjohn.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=464"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mityjohn.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=464"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}