<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>RSS Feed for Good Enough Testing</title>
    <description>Good Enough Testing - live practical workshops to get better at writing effective test cases</description>
    <link>https://goodenoughtesting.com/articles/feed</link>
    <item>
      <title>Tests Verify Behavior, Types Verify Structure</title>
      <description>&amp;lt;p&amp;gt;Working with LLMs to generate code has made me think deeply about the relationship between tests and types. Both matter for code correctness, but they provide fundamentally different kinds of confidence.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Tests verify behavior&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Tests answer a straightforward question: &amp;lt;strong&amp;gt;Does the system behave as expected in these scenarios?&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;They provide concrete evidence that specific cases work. When you run your test suite and see green, you know those particular scenarios pass. Tests also protect against regressions. When you refactor code or add new features, your existing tests catch breaks in functionality you already built. During development, they give you fast feedback about whether your changes work. &amp;lt;a href=&amp;quot;https://booklet.goodenoughtesting.com/1/good-enough-testing-for-developers/1/what-is-testing-for-a-developer&amp;quot;&amp;gt;I wrote about how to think about testing as developer&amp;lt;/a&amp;gt; and what purpose does the tests have for your development process.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But tests have clear limits. They only check what you thought to test. If you miss an edge case or make wrong assumptions about how the system should behave, your tests will pass while bugs remain. Passing tests do not mean there are no bugs. So they are as strong as your understanding of the product, target market, business goals, and user needs.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Tests give you confidence through examples. They show that specific inputs produce expected outputs.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Types verify structure&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Types answer a different question: Can this category of errors happen?&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;They provide guarantees before running the code. A type checker validates your program structure without executing it. Types eliminate entire categories of invalid states. If your type system says you cannot pass a string where an integer is expected, that error simply cannot occur at runtime. They also make refactoring safer. When you change a function signature, the type checker finds every place that needs updating.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But types also have limits. They express structure, not business logic. A function that takes two integers and returns an integer might be typed correctly but still implement the wrong calculation. Types cannot encode real-world correctness. They prevent structural mistakes but allow logical ones.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Types give you confidence through constraints. They restrict what operations are possible on your data.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;The reality with LLMs&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;When generating code with LLMs, this distinction becomes crucial.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;LLMs are surprisingly good at producing structurally valid code. Modern language models understand syntax, common patterns, and basic type requirements. The real problem is they often generate code that compiles and runs but does the wrong thing.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;They make wrong assumptions about your requirements. They miss edge cases you forgot to mention. They misunderstand the business logic you tried to describe. The code looks right and passes basic structural validation, but it implements the wrong behavior.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;This is where tests become essential. A test suite that captures what the code should actually do catches these subtle logic errors that types cannot see. Types help ensure the code is structurally sound, but tests validate that the LLM understood what you needed.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;What developers have proven&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Developers in dynamically-typed languages like Ruby have built massive, reliable systems with comprehensive tests and no static types for decades. These systems handle millions of users and billions of dollars in transactions.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The pattern is consistent: Strong test coverage catches the errors that matter in production. Tests verify the actual behavior users depend on.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;When working with LLM-generated code, this pattern holds even more strongly. The generated code might satisfy type constraints easily, but only tests tell you if it solves your actual problem.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Both matter, differently&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;I am not arguing against types. In statically-typed languages, types catch whole classes of errors automatically. They make code easier to refactor and maintain. They provide valuable documentation about structure.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But when evaluating LLM-generated code, tests provide the confidence you need most. They verify that the system does what you intended, not just that it satisfies structural requirements.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The code might be perfectly typed and completely wrong. Tests catch that. The code might lack type annotations but work exactly as needed. Tests verify that too.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Both tests and types improve code quality, but they do it through different mechanisms. Understanding this difference helps you work more effectively with LLMs to generate reliable code.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2026-01-17</pubDate>
      <link>https://goodenoughtesting.com/articles/testing-and-types-in-context-of-llms</link>
      <guid>https://goodenoughtesting.com/articles/testing-and-types-in-context-of-llms</guid>
    </item>
    <item>
      <title>A short review of study "How Many Instructions can LLMs Follow at Once?"</title>
      <description>&amp;lt;p&amp;gt;While trying to determine how many instructions are enough in an Agents.md file, I found the following paper:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://arxiv.org/abs/2507.11538&amp;quot;&amp;gt;Jaroslawicz, D., Whiting, B., Shah, P., &amp;amp; Maamari, K. (2025). How Many Instructions Can LLMs Follow at Once? arXiv:2507.11538&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Before reading what I extracted from there I think it is important to understand the limitations defined by authors:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Our study has several important limitations. We focus exclusively on professional report generation with simple keyword-inclusion instructions, which may not generalize to other task types or domains, or more complex instruction types. Our business vocabulary from SEC 10-K filings limits insights into other instruction formats common in real applications. Results are specific to English-language, business-domain instruction following, with cross-lingual performance and other paradigms requiring future investigation.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;I still think the study is relevant for developers when thinking about writing guidelines LLM agents or working with an agent and writing more complex prompts.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Findings from the study “How Many Instructions can LLMs Follow at Once.”&amp;lt;/h2&amp;gt;

&amp;lt;h3&amp;gt;There is a bias toward earlier instructions and lower accuracy as the instruction count approaches 500.&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;We evaluate 20 state-of-the-art models across seven major providers and find that even the best frontier models only achieve 68% accuracy at the max density of 500 instructions
Our analysis reveals model size and reasoning capability to correlate with 3 distinct performance degradation patterns, bias towards earlier instructions, and distinct categories of instruction-following errors&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;Be conservative with the total number of instructions. Even under controlled conditions, performance degrades as the number of instructions increases.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Limit the context provided in AGENTS.md or CLAUDE.md files. One way to do this while still providing necessary information is to use progressive disclosure.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Few instructions are better.&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Threshold decay: Performance remains stable until a threshold, then transitions to a different (steeper) degradation slope and displays increased variance. The top two models ( gemini-2.5-pro , o3 ) demonstrate this clearly, maintaining near-perfect performance through 150 or more instructions before declining. Notably, these are both reasoning models, indicating that deliberative processing architectures provide robust instruction tracking up to critical thresholds, beyond which systematic degradation occurs.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;The best reasoning models in this paper, such as gemini-2.5-pro and o3, show a performance decay pattern. They maintain performance up to about 150 or more instructions before a systematic decline, especially for simple, repetitive constraints. In the paper, they used a list of keywords for a business report, as tested in the IFScale benchmark.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Models exhibit a primacy effect, meaning they are generally better at satisfying instructions that appear earlier in the list.&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Primacy effects refer to the tendency of models to better satisfy instructions appearing earlier versus later in the instruction list
Primacy effects display an interesting pattern across all models: they start low at minimal instruction densities indicating almost no bias for earlier instructions, peak around 150-200 instructions, then level off or decrease at extreme densities. This mid-range peak suggests that models exhibit the most bias as they begin to struggle under cognitive load at moderate densities.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;One takeaway is to place the most critical instructions at the beginning of the prompt. This bias is stronger when the model is under moderate cognitive load, around 150 to 200 instructions. However, relying on ordering is less effective at extreme densities, above 300 instructions, where models are overwhelmed and fail uniformly.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;My takeaways&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;After reading that study here are some takeaways I noted down mostly for me:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;1. Be conservative with how many instructions you include in AGENTS.md/CLAUDE.md&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Long instruction lists degrade model performance. Aim for under 150 instructions if possible.
If you reach 200+, expect accuracy drops.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;In case of prompting, avoid giant “superprompts.”&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;2. Put the most important rules first&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Models consistently show a primacy effect: they are better at following instructions that appear earlier in the list. Always put your most critical requirements first.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Place safety rules and project-critical constraints in the first 10–20 items.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;3. Use progressive disclosure&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Don’t dump everything into one big file and break guidelines into layers or steps.
Practical ways to do this:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Split instructions by themes (coding, style, architecture).&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Send only the section relevant to the current task.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use “ask-if-needed” patterns instead of hard-coding everything upfront.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;4. Prefer fewer, better instructions&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Redundant, verbose, or repetitive rules increase instruction count and reduce accuracy, even though they degrade in effectiveness when the number of instructions is high.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Simple, repetitive instructions hold up better than complex or varied ones, but even these degrade in effectiveness at high counts.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;5. Use structured formats instead of long prose&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Models track clearer instructions when the structure is consistent.
Examples:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Use bullet points instead of paragraphs.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use tables for dos/don’ts.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use “If X, then Y” rules.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use numbered steps&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;This improves recall in most normal cases.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;6. Let the model summarize your instructions for internal use&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;One way to reduce the number of rules is to ask the model to summarize or restate your instruction set in its own words. Make sure you read them and check if they maintain the same spirit or intention as the original prompt.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-12-04</pubDate>
      <link>https://goodenoughtesting.com/articles/how-many-instructions-are-enough</link>
      <guid>https://goodenoughtesting.com/articles/how-many-instructions-are-enough</guid>
    </item>
    <item>
      <title>Highlights from "Do LLMs Generate Test Oracles That Capture The Actual Or The Expected Program Behaviour?"</title>
      <description>&amp;lt;p&amp;gt;There’s a lot of discussion about using LLMs to build applications, including generating test cases. It’s interesting to read people’s experiences and see how LLMs are affecting software development. Opinions on the usefulness of LLMs range from very positive to quite negative.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;To make sense of these different experiences, I decided to look at research studies about using LLMs for testing. I’ll focus on development in another article.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I plan to share some highlights as I review different studies on how generative LLMs are used for testing.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I’ll start with a 2024 study titled &amp;lt;strong&amp;gt;&amp;ldquo;Do LLMs generate test oracles that capture the actual or the expected program behaviour?&amp;rdquo;&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;pre&amp;gt;
Konstantinou, Michael &amp;amp; Degiovanni, Renzo &amp;amp; Papadakis, Mike. (2024).
Do LLMs generate test oracles that capture the actual or the expected program behaviour?.
10.48550/arXiv.2410.21136.
&amp;lt;/pre&amp;gt;

&amp;lt;p&amp;gt;Before I continue, I want to clarify two important points:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Test Oracle&amp;lt;/strong&amp;gt;: &amp;ldquo;A test oracle is a mechanism that determines whether software executed correctly for a test case&amp;rdquo; (&amp;lt;a href=&amp;quot;https://ieeexplore.ieee.org/document/1240304&amp;quot;&amp;gt;source&amp;lt;/a&amp;gt;) or &amp;ldquo;A source to determine an expected result&amp;rdquo; (&amp;lt;a href=&amp;quot;https://glossary.istqb.org/en_US/term/test-oracle&amp;quot;&amp;gt;source&amp;lt;/a&amp;gt;)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Content of the study&amp;lt;/strong&amp;gt;: The paper’s results are based on tests with OpenAI GPT 3.5-turbo in 2024, so newer models may have improved. Still, I think the insights from this study are valuable for understanding AI-driven test generation.&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;I’ve picked out some key points from the study and will share my thoughts on each of them.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;LLMs Mirror Code, Not Intentions&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Interestingly, our results show that LLMs are more likely to generate test oracles that capture the actual program behaviour (what is actually implemented) rather than the expected one, i.e., the intended behaviour.
Additionally, we find that the overall performance of the LLMs is relatively low (less than 50% accuracy) meaning that LLMs do not provide a strong oracle correctness signal. Therefore, all LLMs suggestions will need human inspection.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;This suggests that when LLMs are asked to generate test cases and assertions without clear requirements, they tend to follow the code itself. In my view, to use LLMs effectively for test generation, you need well-written requirements so the LLM can use them to create test oracles.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Another situation is when your codebase lacks test cases and you want to add tests before refactoring. If you focus on the functional behavior, given certain inputs, the code should produce specific results, an LLM can help generate these kinds of test cases.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;LLMs can boost code coverage but require human help for correct behavior&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;While effective at covering code (or killing mutants), automatic test generation falls short in finding faults, particularly business-logic related faults. This is because of the inherent inability of these techniques to compose test oracles (test assertions) that capture the expected program behaviour. This means that the fault detection ability of these techniques is limited to zero-level oracles, such program crashes or memory violations (when applied at system level).&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;This supports the idea I mentioned earlier: you can use LLMs to increase test coverage and focus on documenting your code’s current functional behavior.&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;To reveal business-logic software faults with test generation techniques one need to manually validate and correct, when needed, the generated tests and their respective oracles&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;This is the approach I recommend (for now) in my workshops: when using LLMs to generate test cases, a human should always review them to ensure the tests check for the intended behavior, not just what the code currently does.&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Our experiments showed that the LLM&amp;rsquo;s accuracy to correctly classify a correct assertion as positive, drops when the given code is buggy. This suggest that the LLM is prone to follow the actual implementation to classify the test oracle rather than the expected behaviour.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;If your code has a bug that isn’t obvious business logic, the LLM will likely generate test cases that follow the bug, since it can’t guess your intentions without requirements. However, if you’re working with common patterns or business logic that LLMs have seen during training, they might spot issues. I’ve seen cases where LLMs, when asked to write tests, also reviewed the code and pointed out bugs that needed fixing.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But if you’re working on something specific, the LLM may not be able to point out bugs that need to be fixed.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If you’re writing code that’s specific to your domain and not just boilerplate, you can’t rely on LLMs to write good assertions. You’ll need to review what they generate.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Meaningful names help LLMs in generating tests&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Taken together, our results corroborate the conclusion that unless having meaningful test or variable names LLMs can mainly be used to capture the actual program behaviour (thus to be used for regression testing).&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;Although the paper focused on Java, I think the idea can apply to other languages too. For example, in Ruby, where developers often use meaningful names for variables and methods and pay attention to domain context, this should help LLMs generate better test oracles, according to the study.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Two-Step Workflow&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;In TDD, you usually have requirements before writing code. You can use a two-step workflow: first, give the requirements and ask the LLM to identify what’s testable, then ask it to write tests. This way, the requirements act as the test oracle, and the LLM is more likely to write good test assertions based on them instead of just the implementation.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If you write the implementation first and then want to generate test cases, you can still use a two-step workflow. First, describe the purpose of your code and provide any other sources as a test oracle. Ask the LLM to review them and identify what should be tested, then give it the code and ask it to generate test cases.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-11-07</pubDate>
      <link>https://goodenoughtesting.com/articles/llms-test-generation-research-insights</link>
      <guid>https://goodenoughtesting.com/articles/llms-test-generation-research-insights</guid>
    </item>
    <item>
      <title>Use LLMs to generate either tests or code, but not both</title>
      <description>&amp;lt;p&amp;gt;When using LLMs in software development, it&amp;rsquo;s important to be aware that generating both tests and code simultaneously can lead to significant risks. Therefore, use LLMs to generate either tests or code, but not both. For complex problems or business logic, I recommend using LLMs to generate either tests or code, but not both.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Using LLM to generate both in the same session has two main risks:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Source of truth:&amp;lt;/strong&amp;gt; When an LLM writes tests, it assumes the source code is correct and aims to confirm the code works as intended. This is even more real when the domain where you are trying to solve a problem that maybe is not so common or diverges from some common assumption in some specific way.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;Confirmation bias:&amp;lt;/strong&amp;gt; This can lead to confirmation bias and make it difficult to identify bugs, especially when reviewing large volumes of generated code.&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;A more effective approach is to &amp;lt;strong&amp;gt;use LLMs for either test case generation or code writing, but not both simultaneously&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;When LLMs generate test cases, remember that we generally lack automated methods to verify their accuracy or ensure they assess the intended requirements.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;You might want to use LLMs to generate both tests and code, but you should do that in stages: generate the first asset, review it, change it if needed and then generate the second asset. Human-in-the-loop review if essential to have maintain a good quality and lower the risk of failures.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;To help LLMs generate effective tests that target critical areas, ensure the features you are building are thoroughly documented. Enhance the feature specification by including:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;Examples relevant to the feature&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;A clear definition of the target user group&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Decision tables or truth tables for any relevant conditions&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;The more detailed the specification, the better context the LLM receives, resulting in more relevant tests. However, avoid providing excessive context, as this may cause the LLM to overfit to narrow scenarios.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-11-04</pubDate>
      <link>https://goodenoughtesting.com/articles/use-llms-to-generate-test-or-code-but-not-both</link>
      <guid>https://goodenoughtesting.com/articles/use-llms-to-generate-test-or-code-but-not-both</guid>
    </item>
    <item>
      <title>Shortly about tests generated by LLMs</title>
      <description>&amp;lt;p&amp;gt;LLMs can write a lot of tests. But let’s not confuse a lot of tests with good tests.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;For instance, a single well designed test could prevent a major failure that fifty auto-generated ones might miss (of course there the proportion is relative).&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Too many tests can bring a couple of issues:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;They increase the time to run your test suite. Even a fast test suite cannot keep up with the number of tests an LLM will generate by default.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;They have to be maintained. If you use LLMs to write both tests and code, you still need to review the changes. The more tests you have, the more will change, and the more lines you must read in the diff.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;They have to be understood. When debugging, tests help you understand current behavior, but the more tests you have, the more time you spend reading possibly duplicate documented behavior.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;They add to the context. The more tests you have, the more an LLM needs to read. If you generate tests with LLMs and use them as is, you are feeding back what the LLM generated and only increasing the context.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;Keep tests that matter: those that verify requirements, document specific behavior, or help replicate edge cases.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-10-27</pubDate>
      <link>https://goodenoughtesting.com/articles/on-tests-generated-by-llms</link>
      <guid>https://goodenoughtesting.com/articles/on-tests-generated-by-llms</guid>
    </item>
    <item>
      <title>Add comments to your database for humans and LLMs</title>
      <description>&amp;lt;p&amp;gt;Add comments to your Rails migrations. This helps the next developer understand your intent and also helps an LLM follow your product decisions.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Explaining why a column exists or how you chose its name turns your schema into a mini README. This small step helps both people and machines better understand your code.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Example&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Here&amp;rsquo;s an example of a topics table that stores themes used for talks at different events.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;While the following example is from Ruby on Rails you should do this no matter the programming language or framework used.&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;ruby&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #8ec07c&amp;quot;&amp;gt;CreateTopics&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;&amp;lt;&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;ActiveRecord&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;::&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;Migration&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;8.0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;
  &amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;def&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;change&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;create_table&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:topics&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Reusable themes that group talks across events. Support discovery by theme.&amp;quot;&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;do&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;|&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;integer&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:canonical_id&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;References the canonical topic when duplicates are merged. Used for redirects and metric consolidation.&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;string&amp;lt;/span&amp;gt;   &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:name&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;limit: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;80&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Unique public name. Human readable&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;string&amp;lt;/span&amp;gt;   &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:slug&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;         &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;null: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;default: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;&amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Slug used in URLs and API paths. Auto generated from name. Changing this will break existing links.&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;string&amp;lt;/span&amp;gt;   &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:status&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;       &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;null: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;default: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;pending&amp;quot;&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Moderation state. Moves from pending to approved to archived after review.&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;boolean&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:published&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;    &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;default: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Controls public visibility. Visible only if status is approved and this flag is true.&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;text&amp;lt;/span&amp;gt;     &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:description&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Public summary. One to three sentences. Shown on topic pages and in search results.&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;integer&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:talks_count&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;  &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;null: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;default: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;0&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Counter cache for associated talks. Updated automatically through the Talk model.&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;datetime&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:created_at&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;   &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;null: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Managed by Rails. Used for ordering and audit trails.&amp;quot;&amp;lt;/span&amp;gt;
      &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;t&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;datetime&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:updated_at&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt;   &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;null: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;false&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;comment: &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Managed by Rails. Updated when topic content changes.&amp;quot;&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;end&amp;lt;/span&amp;gt;
  &amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;In case you already have created your tables and run your migrations you can add comments in Ruby on Rails to your schema using &amp;lt;code&amp;gt;change_table_comment&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;change_column_comment&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;ruby&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #8ec07c&amp;quot;&amp;gt;AddCommentsToSchema&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;&amp;lt;&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;ActiveRecord&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;::&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;Migration&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;[&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;6.1&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;]&amp;lt;/span&amp;gt;
  &amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;def&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;change&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;change_table_comment&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:topics&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Reusable themes that group talks across events. Support discovery by theme&amp;quot;&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;change_column_comment&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:topics&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:name&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Unique public name. Human readable&amp;quot;&amp;lt;/span&amp;gt;
    &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;change_column_comment&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:topics&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #83a598&amp;quot;&amp;gt;:slug&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;,&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;&amp;quot;Slug used in URLs and API paths. Auto generated from name. Changing this will break existing links.&amp;quot;&amp;lt;/span&amp;gt;
  &amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;/pre&amp;gt;
&amp;lt;h3&amp;gt;Why some of these comments matter&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Let&amp;rsquo;s take a look at some of them and what is the intention behind those comments.&amp;lt;/p&amp;gt;

&amp;lt;h4&amp;gt;Documenting the main table &amp;lt;code&amp;gt;topics&amp;lt;/code&amp;gt;&amp;lt;/h4&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Reusable themes that group talks across events. Support discovery by theme&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;This comment explains the reason behind the table, not just its purpose. It helps newcomers see how this table fits into the product.&amp;lt;/p&amp;gt;

&amp;lt;h4&amp;gt;Documenting the &amp;lt;code&amp;gt;canonical_id&amp;lt;/code&amp;gt;:&amp;lt;/h4&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;References the canonical topic when duplicates are merged. Used for redirects and metric consolidation.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;Without this note, a developer might assume it&amp;rsquo;s a foreign key to a different table or maybe a self-reference on the same table. But with the comment, it&amp;rsquo;s clear that it&amp;rsquo;s a self-reference used during merges.&amp;lt;/p&amp;gt;

&amp;lt;h4&amp;gt;Documentation on &amp;lt;code&amp;gt;slug&amp;lt;/code&amp;gt;&amp;lt;/h4&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Slug used in URLs and API paths. Auto generated from name. Changing this will break existing links.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;This comment makes it clear that changing the slug could break links. It also lets you know that slugs usually aren&amp;rsquo;t changed after publishing.&amp;lt;/p&amp;gt;

&amp;lt;h4&amp;gt;Documentation on &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;published&amp;lt;/code&amp;gt;:&amp;lt;/h4&amp;gt;

&amp;lt;p&amp;gt;For the status:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Moderation state. Moves from pending to approved to archived after review&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;It explains what is the purpose of the status (&amp;ldquo;moderation&amp;rdquo;) and how it changes over time with some examples without going full into the enum for that status.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;For the published field:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Controls public visibility. Visible only if status is approved and this flag is true&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;It explains what is the purpose of the published field (&amp;ldquo;visibility&amp;rdquo;) and how it should be considered together with &amp;lt;code&amp;gt;status&amp;lt;/code&amp;gt;. These fields control visibility. The comment explains that a topic needs to be both approved and published to show up, which helps future developers avoid mistakes.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Writing these comments well takes practice&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;You might not get every comment perfect the first time. Some are tricky because they cover both business and technical details. Some others are tricky if you, like me, are not a native English speaker. That&amp;rsquo;s okay.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The goal isn&amp;rsquo;t perfect comments, it&amp;rsquo;s to reduce confusion and make your intent clear. Even a short note like &amp;lsquo;used for redirects&amp;rsquo; or &amp;lsquo;set by background job&amp;rsquo; is better than nothing.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Each comment you add now means fewer mysteries for you or others later.
Start with small comments and improve them over time.
Your future self, your teammates, and even your LLMs will appreciate it.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-10-25</pubDate>
      <link>https://goodenoughtesting.com/articles/comment-your-database-for-humans-and-llms</link>
      <guid>https://goodenoughtesting.com/articles/comment-your-database-for-humans-and-llms</guid>
    </item>
    <item>
      <title>Tests as the line of defense for AI generated code</title>
      <description>&amp;lt;p&amp;gt;Being good at testing is a skill developers should sharpen even more when using LLMs to generate code. Especially if you:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;Use the LLM in agentic mode.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use LLMs to solve hard problems or implement complicated business logic.&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;Your test cases are the best line of defense to ensure the generated code works as intended. Good tests should be fast, isolated, and intention-revealing. They should quickly identify faults in the code without dependencies that can skew results and clearly communicate what they are testing. Here&amp;rsquo;s a brief checklist to determine if your tests are effective in defending against faulty LLM outputs:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Is the test fast enough to run frequently?&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Does it function independently without impacting or being affected by other tests?&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Does it clearly state the intention of what it is verifying?&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Does it cover critical business requirements or edge cases?&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Is it easy to understand and maintain over the long term?&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;Always review the code generated by an LLM. While writing good test cases is essential, it does not replace the need for a thorough code review. Targeted tests can effectively guide your LLMs to create better solutions with fewer chances of dangerous bugs.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;In the end, you still have to assume and own the solution created with LLMs.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-10-21</pubDate>
      <link>https://goodenoughtesting.com/articles/tests-as-line-of-defense-when-using-llms</link>
      <guid>https://goodenoughtesting.com/articles/tests-as-line-of-defense-when-using-llms</guid>
    </item>
    <item>
      <title>Resources to use when you want to test strings</title>
      <description>&amp;lt;h2&amp;gt;Resources useful for testing strings&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;In case you really need in your test suite to handle real strings of various types, here are some resources you can use:&amp;lt;/p&amp;gt;

&amp;lt;h4&amp;gt;The Big List of Naughty Strings:&amp;lt;/h4&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/minimaxir/big-list-of-naughty-strings&amp;quot;&amp;gt;https://github.com/minimaxir/big-list-of-naughty-strings&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;The Big List of Naughty Strings is an evolving list of strings which have a high probability of causing issues when used as user-input data.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;h4&amp;gt;Faker gem:&amp;lt;/h4&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/faker-ruby/faker&amp;quot;&amp;gt;https://github.com/faker-ruby/faker&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;A library for generating fake data such as names, addresses, and phone numbers.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;h4&amp;gt;SecLists Username and Passwords:&amp;lt;/h4&amp;gt;

&amp;lt;p&amp;gt;SecList sections about Username and Passwords if you want to test authentication:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Passwords: &amp;lt;a href=&amp;quot;https://github.com/danielmiessler/SecLists/tree/master/Passwords&amp;quot;&amp;gt;https://github.com/danielmiessler/SecLists/tree/master/Passwords&amp;lt;/a&amp;gt; -&amp;gt; &amp;lt;em&amp;gt;&amp;ldquo;The Passwords directory will hold a number of password lists that can be used by multiple tools when attempting to guess credentials for a given targeted service&amp;rdquo;&amp;lt;/em&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Usernames: &amp;lt;a href=&amp;quot;https://github.com/danielmiessler/SecLists/tree/master/Usernames&amp;quot;&amp;gt;https://github.com/danielmiessler/SecLists/tree/master/Usernames&amp;lt;/a&amp;gt; -&amp;gt; &amp;lt;em&amp;gt;&amp;ldquo;The Usernames directory will hold a number of username lists that can be used by multiple tools when attempting to guess credentials for a given targeted service&amp;rdquo;&amp;lt;/em&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;h4&amp;gt;List of Dirty, Naughty, Obscene, and Otherwise Bad Words&amp;lt;/h4&amp;gt;

&amp;lt;p&amp;gt;This is an old list of dirty, naughty, obscene, and otherwise bad words that can be used to test your application&amp;rsquo;s ability to handle such content.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://github.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words&amp;quot;&amp;gt;https://github.com/LDNOOBW/List-of-Dirty-Naughty-Obscene-and-Otherwise-Bad-Words&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;h4&amp;gt;A list of hostnames and usernames to reserve&amp;lt;/h4&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://ldpreload.com/blog/names-to-reserve&amp;quot;&amp;gt;https://ldpreload.com/blog/names-to-reserve&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I tried to compile what is in that article and make simple .txt files &amp;lt;a href=&amp;quot;https://github.com/lucianghinda/list-of-usernames-hostnames-and-emails-to-reserve&amp;quot;&amp;gt;in this repo&amp;lt;/a&amp;gt; where I added a bit more.&amp;lt;/p&amp;gt;

&amp;lt;h4&amp;gt;UI Testing Checklist&amp;lt;/h4&amp;gt;

&amp;lt;p&amp;gt;Some ideas about Strings and other formats to use when submitting UI forms:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://www.scribd.com/document/507622474/UI-Testing-Checklist&amp;quot;&amp;gt;https://www.scribd.com/document/507622474/UI-Testing-Checklist&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-10-13</pubDate>
      <link>https://goodenoughtesting.com/articles/resources-for-developers/strings</link>
      <guid>https://goodenoughtesting.com/articles/resources-for-developers/strings</guid>
    </item>
    <item>
      <title>Good Tests Begin with Good Samples</title>
      <description>&amp;lt;p&amp;gt;Make your future easier by spending time today to properly set up test data.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The time you spend today setting up test data that matches real and important user cases is an investment.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;It will help your daily work but it will be a great help during a priority zero incident, and you will be glad you invested that time early.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;To achieve this, understand your users, your product, and your business. Work closely with your product, support, and sales teams, then apply sampling.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Choosing good test data is about sampling well. Borrowing ideas from statistics helps us make smarter, more deliberate choices.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;1. Population vs. Sample&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Think of your code’s input space as a population: every possible combination of data and state.
Your tests are a sample of that population.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The goal isn’t to test everything, but to test a representative subset that helps you discover likely problems early.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;2. Random vs. Systematic Sampling&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;You can:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Pick random inputs (great for fuzz testing or probabilistic code), or&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Pick systematic samples, one from each meaningful category or boundary.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;For most business logic, structured sampling works best.
Example:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If your API accepts ages 0 to 120, you don’t need 100 random ages.
You need a few key samples:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;0 (lower boundary)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;1 (typical valid)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;119 and 120 (upper boundaries)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;121 (invalid)&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;This approach is actually the folundation for boundary value analysis testing technique.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;3. Stratified Sampling: Covering All Groups&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Not all inputs are equal.
Divide your input space into logical groups and pick samples from each one.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Example:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;For a login form, you might stratify by “valid credentials,” “invalid password,” “nonexistent user,” “empty input.”
Then pick one or two cases from each.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;This prevents over-testing one area and missing others.
In testing terms: that’s a part of the equivalence partitioning testing technique.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;4. Sampling Bias: The Trap of “Happy Paths”&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Most developers unintentionally sample the same region, sometimes called the happy path.
The result is biased tests that miss the tricky edge cases where bugs often hide.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Ask yourself:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Are my test cases representative of real-world usage and rare conditions?&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;If 90% of your users are on mobile Safari, don’t just test on desktop Chrome.
If your code processes files, test both small and large ones, and consider different file extensions. See the stratified sampling.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;5. How Many Samples Are Enough?&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Adding more test data isn’t always better.
Beyond a certain point, new samples might reveal new information, but adding more to an already covered space increases testing costs.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Think of sampling like this:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Start broad: cover each risk area once.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Go deeper only where you see instability or recent changes.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;This is called risk-based coverage: you focus your effort where it matters most and avoid unnecessary work.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;6. Always Include Extremes and Weirdness&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Include a few “troublemakers”:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Empty strings&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Nulls&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Maximum lengths&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Invalid characters&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Very large numbers&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;These aren’t just edge cases. They’re bug magnets.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;7. Realistic vs. Synthetic Data&amp;lt;/h2&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Synthetic data helps you test logic cleanly and deterministically.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Realistic data reveals integration issues, performance surprises, and messy real-world inputs.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;You need both.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;For example, your happy path tests can use synthetic data, but your end-to-end suite should include a realistic snapshot of production-like data.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;8. Adaptive Sampling&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;You don’t have to get it right from the start.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Start small.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;When a bug appears, expand your sample around that area.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Think of it as zooming in with a magnifying glass to spot where problems start to appear.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;9. Things to keep in mind&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Good test data isn’t random.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Good test data is chosen carefully, based on structure, boundaries, and risk.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Next time you write a test, ask:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;What’s the space input here?&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Which categories or boundaries matter most?&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Am I sampling fairly across them?&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Where might the system behave differently?&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;That’s not over-engineering.
That’s just good sampling, and it makes testing much easier.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-10-08</pubDate>
      <link>https://goodenoughtesting.com/articles/test-data-and-sampling</link>
      <guid>https://goodenoughtesting.com/articles/test-data-and-sampling</guid>
    </item>
    <item>
      <title>The Art of Knowing Which TDD Tests to Delete</title>
      <description>&amp;lt;p&amp;gt;Not all tests written during TDD belong in your codebase. While this might be familiar wisdom, it&amp;rsquo;s important to reiterate it here.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;A commit is an artifact&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;I see a commit as an artifact of my work: it can deliver value or be examined to understand its functionality and how to fix issues. From this perspective, the tests included in the commit are essential for understanding how the code works and ensuring it performs as intended. In this case the tests included in a commit should be carefully selected.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;TDD is a practice not a test design technique&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;TDD is a software development practice, not a testing or test design technique. Tests written during TDD serve different purposes depending on when they are written.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;At the end of this practice, you will have tests that drove your development and a piece of business logic that satisfies some functional or non-functional requirements.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;During your TDD process, you might have written a range of test types at various levels:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;You may have written some functional unit testing&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;You may have written some non-functional integration testing&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;You may have written some functional system or acceptance testing&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;h2&amp;gt;Keep the tests that satisfy these criteria&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;When preparing to commit, you have to remove the tests that were driving your process and keep the ones that satisfy at a minimum the following criteria:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;They verify that the implementation satisfies the requirements. Ask: &amp;lt;em&amp;gt;&amp;ldquo;Does this test ensure my code accomplishes what it&amp;rsquo;s supposed to do based on the specifications?&amp;rdquo;&amp;lt;/em&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;They document code behaviou to help maintainability (including debugging, support, and changing. Consider: &amp;lt;em&amp;gt;&amp;ldquo;Will this test help a developer understand the code or diagnose issues in the future?&amp;rdquo;&amp;lt;/em&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;They check that a specific shape, attribute, or form of the code or architecture ei important for the component you are developing , such astesting that a new object inheriting from a parent needs to define a specific method). Ask: &amp;lt;em&amp;gt;&amp;ldquo;Is this structural test crucial for ensuring the component functions correctly in its intended context?&amp;rdquo;&amp;lt;/em&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;For example, a test that verifies a method outputs correct results based on given inputs would meet these criteria, as it ensures the functionality aligns with the requirements.If you have tests that guided your code design but offer no further benefit, you should delete them.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Example of tests to remove&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Here are some categories of tests that could be created during a TDD session and that you might consider removing. This is not an exhaustive list, and depending on your context, you might want to keep some, for example, to pin specific implementation details for performance or security reasons.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;There are instances when keeping such tests is justified, such as when dealing with legacy code where comprehensive documentation is lacking. Compliance may also require specific tests to meet regulatory standards or to demonstrate that certain conditions have been met. Additionally, in scenarios where performance is critical, keeping some of these tests can help ensure that the system performs optimally under various conditions.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Scaffolding tests used purely for design exploration:&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Existence/scaffolding tests (from the category of make it work, like testing that an object exists)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tests written to explore different API designs before settling on the final interface&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Experimental tests for approaches you ultimately rejected&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;ldquo;Spike&amp;rdquo; tests used to understand how a third-party library works&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Tests that verify implementation details rather than behaviour:&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Tests that check private method implementations&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tests that verify the exact sequence of internal method calls&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tests that assert on specific data structure choices (e.g., &amp;ldquo;must use a HashMap&amp;rdquo;) when the requirement is just &amp;ldquo;fast lookups&amp;rdquo;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Over-specified tests that constrain refactoring:&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Tests that verify exact error message wording when the requirement is just &amp;ldquo;must fail gracefully&amp;rdquo;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tests that assert on specific class structures when the requirement is about behaviour&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tests that mock every dependency when testing at a higher level would be more valuable&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Duplicate tests at the wrong abstraction level:&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Low-level unit tests that duplicate what acceptance tests already verify&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tests for trivial getters/setters with no business logic&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Tests for framework behavior rather than your code&amp;rsquo;s behavior&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;The key question to ask:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;If this test breaks, does it tell me something valuable broke, or just that I changed how I implemented something?&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;
</description>
      <pubDate>2025-10-06</pubDate>
      <link>https://goodenoughtesting.com/articles/the-art-of-knowing-which-tdd-tests-to-delete</link>
      <guid>https://goodenoughtesting.com/articles/the-art-of-knowing-which-tdd-tests-to-delete</guid>
    </item>
    <item>
      <title>What We Lost When QA Teams Disappeared</title>
      <description>&amp;lt;p&amp;gt;In many companies over the last 15 years, QA teams have diminished or even disappeared.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The tech industry decided we do not need special QA teams because everyone should care about quality. As companies aimed to be more flexible and moved away from old step-by-step methods, they stopped using QA as the final check before releases and instead encouraged the whole team to work together.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I think this concept became popular around 2009. The best resource on this is Lisa Crispin and Janet Gregory’s book, &amp;lt;em&amp;gt;Agile Testing: A Practical Guide for Testers and Agile Teams&amp;lt;/em&amp;gt; (2009).&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Thinking about quality from the beginning is great. It is like handling security or privacy: you have to start as soon as you define what the product should do. Adding quality, security, or privacy at the end is expensive, takes longer, and delays benefits for users.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Developers doing more testing&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;I want to focus on the impact this has on developers, especially regarding testing practices.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Focusing on quality early led to more automated testing. Developers began testing their own work, mostly using automated tools. This is good. To achieve high product quality, we need to start with quality from the beginning, and everyone involved should pay attention to it.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Developers are good at writing tools and automating tasks, so more testing tools and better automation environments were created. As a result, more code is now covered by tests.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Do we have the right tests in place?&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Having close to 100% code coverage with automated tests might sound like a great metric. It is useful because any line of code not executed could cause a failure in production. However, these metrics mostly refer to line coverage, which can be achieved in different ways, sometimes without testing important cases for certain users. This shows a team can have good test coverage but still miss important quality or functional targets.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Developers and testing skills&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Most schools and programs that teach software development do not have a proper curriculum for testing. Testing is usually taught as writing unit tests or learning a framework, not as a skill. It is mostly seen as a way to evaluate code, not the holistic product or its value from a quality perspective.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;In practice, developers pick up testing skills as they go. If you were in a good culture led by someone who knew testing philosophy and practices, you probably have decent or great testing skills. If not, you may still write tests just to show the code works as written. This is better than having no tests, but these tests might miss important or critical cases for the business and end-users.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Reflect on your own testing habits. Are there areas where your skills might be lacking? Are your tests effectively capturing the needs of your end-users? By regularly evaluating your testing strategies, you can identify gaps in your knowledge and take steps to improve.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Here is an example. Let&amp;rsquo;s look at the following piece of code:&amp;lt;/p&amp;gt;
&amp;lt;pre class=&amp;quot;ruby&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic&amp;quot;&amp;gt;# https://github.com/basecamp/once-campfire/blob/main/app/models/user.rb#L26&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;class&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #8ec07c&amp;quot;&amp;gt;User&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;&amp;lt;&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #d3869b&amp;quot;&amp;gt;ApplicationRecord&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color: #fb4934;background-color: #282828;font-weight: bold&amp;quot;&amp;gt; &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #928374;font-style: italic&amp;quot;&amp;gt;# t.string &amp;quot;name&amp;quot;, null: false&amp;lt;/span&amp;gt;

&amp;lt;span style=&amp;quot;color: #fb4934;background-color: #282828;font-weight: bold&amp;quot;&amp;gt; &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;def&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;initials&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color: #fb4934;background-color: #282828;font-weight: bold&amp;quot;&amp;gt; &amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color: #fb4934;background-color: #282828;font-weight: bold&amp;quot;&amp;gt; &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;name&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;.&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;scan&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;(&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #b8bb26;font-style: italic&amp;quot;&amp;gt;/\b\w/&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7&amp;quot;&amp;gt;).&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fbf1c7;background-color: #282828&amp;quot;&amp;gt;join&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color: #fb4934;background-color: #282828;font-weight: bold&amp;quot;&amp;gt; &amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;span style=&amp;quot;color: #fb4934&amp;quot;&amp;gt;end&amp;lt;/span&amp;gt;
&amp;lt;/pre&amp;gt;
&amp;lt;p&amp;gt;This code is supposed to generate initials from the user&amp;rsquo;s name.
What tests would you write for it?&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;If you focus on achieving 100% code coverage of &amp;lt;code&amp;gt;Users#initials&amp;lt;/code&amp;gt;, a single test is enough.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;You could write two tests by adding a negative one that might throw an exception.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;Both cases overlook an important point: Who are the users of our application, and which countries are they from? Depending on the country, this method might often return empty. For example, if the name is &amp;lt;code&amp;gt;José Ángel&amp;lt;/code&amp;gt;, this would return only &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt;. If the name is &amp;lt;code&amp;gt;佐藤 陽翔&amp;lt;/code&amp;gt;, it will return empty. Maybe this is correct, but my point is that we need test design to uncover for whom we are writing these tests, and then write the tests accordingly.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Knowing who the end-users are and their most common or important use cases is a crucial part of a tester&amp;rsquo;s approach.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;What is currently missing is test design. We know how to implement and execute tests. We can organize and optimize test code, but asking whether these are the right tests is missing from conversations.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;With QA vanished, testing best practices, knowledge and wisdom also vanished&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Here is the problem today: In companies where the testing team is gone, there is no focus on testing as a skill. Whether the tests are good or not is random. It just becomes about numbers: if you write enough tests, you might cover important situations.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I do not like this approach because it is not systematic. We need to increase developers&amp;rsquo; knowledge about testing, especially as developers use LLMs. If you cannot properly ask for a testing concept, you probably will not get it from an LLM. You may get many tests written by an LLM that you have to maintain and execute, but without understanding test design and what to ask for, you might end up with bloat.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;The solution: learn test design&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;The solution is to learn about test design, test design techniques, and discuss how to approach testing in the current context.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Here are some starting points in case you want to learn more about test design: &amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Understand more about the entire test process and where test design fits in.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Clarify the role of testing: it is about risk, priorities, product context, and project constraints. Accept that testing has tradeoffs, and when designing test cases you have to consider this.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Get comfortable with test levels and test types. Choosing what to test depends on where and what you are planning to test.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;How to set test objectives and traceability to requirements, use cases, code, or important artifacts&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Test Design Techniques: mathematically backed ways to cover important areas of your code or requirements systematically. The core of test design is to know these techniques and when to apply them.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Prioritization and risk: ranking test objectives and possible test cases based on risk, and choosing to apply a test design technique to generate more or fewer test cases, is crucial.&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Read about preconditions, postconditions, and the difference between them and assertions. This will help organize your tests even before writing the first line of code.&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;
</description>
      <pubDate>2025-10-02</pubDate>
      <link>https://goodenoughtesting.com/articles/what-we-lost-when-qa-teams-dissapeared</link>
      <guid>https://goodenoughtesting.com/articles/what-we-lost-when-qa-teams-dissapeared</guid>
    </item>
    <item>
      <title>The smallest files of any type to be used in automated testing</title>
      <description>&amp;lt;p&amp;gt;In case you really need in your test suite to handle real files of various types, here are some resources you can use:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;The smallest possible valid PNG image: &amp;lt;a href=&amp;quot;https://evanhahn.com/worlds-smallest-png/&amp;quot;&amp;gt;https://evanhahn.com/worlds-smallest-png&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;The smallest PDF file: &amp;lt;a href=&amp;quot;https://pdfa.org/the-smallest-possible-valid-pdf/&amp;quot;&amp;gt;https://pdfa.org/the-smallest-possible-valid-pdf/&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;But what you should actually bookmark is this repository:
&amp;lt;a href=&amp;quot;https://github.com/mathiasbynens/small&amp;quot;&amp;gt;https://github.com/mathiasbynens/small&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;It has a great collection of the smallest valid files of any type to be used in automated testing.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-09-29</pubDate>
      <link>https://goodenoughtesting.com/articles/resources-for-developers/small-files</link>
      <guid>https://goodenoughtesting.com/articles/resources-for-developers/small-files</guid>
    </item>
    <item>
      <title>New AI Workshop at EuRuKo 2025</title>
      <description>&amp;lt;p&amp;gt;I started working on the workshop for &amp;lt;a href=&amp;quot;https://2025.euruko.org&amp;quot;&amp;gt;EuRuKo 2025&amp;lt;/a&amp;gt;, &amp;ldquo;Don&amp;rsquo;t Let Your AI Guess: Teach It to Test.&amp;rdquo;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Image with announcement about Lucian Ghinda&amp;#39;s workshop at EuRuKo&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/new-workshop-ai-wip.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The goal of this workshop is to introduce techniques for prompting that reduce the hallucinations AI may experience when asked to write tests.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;This is intended for individuals using AI to enhance their coding, allowing them to remain in control of which changes are applied. It&amp;rsquo;s likely unsuitable for fully agentic coding (unsupervised) unless you plan to use these prompts as system instructions for your agent.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Let me start with my core belief: current LLMs are NOT ready to independently write tests that achieve the following goals:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;Verify requirements&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Ensure the software behaves predictably and consistently over time&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Specify current behavior&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;They can generate unit tests that pass by examining the code, whether you or they wrote it. While this is useful, it seems like merely documenting the current code behavior. Without supervision, it&amp;rsquo;s just creating more tests to confirm the code works as it is written.
This resembles verifying requirements, but it is NOT! Verifying requirements involves writing tests based on expected behavior, not on the current business logic in the code. The surse of truth (called test oracle) for a test should be the product requirements, the users needs and the customer expectations and not the code.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If you care about correctness, consider using AI to generate tests, but maintain control:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Select which tests the AI will write&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Review the test data&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Review the assertions&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;Otherwise, you might end up with tests that pass but don&amp;rsquo;t effectively test what&amp;rsquo;s important, leaving your users unprotected from potential bugs.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I plan to do a dry-run of this workshop before the conference and if you want to get invited at a discounted price join &amp;lt;a href=&amp;quot;https://goodenoughtesting.com/subscribers/new&amp;quot;&amp;gt;the GoodEnoughTesting newsletter&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-08-21</pubDate>
      <link>https://goodenoughtesting.com/articles/announcing-the-new-euruko-workshop</link>
      <guid>https://goodenoughtesting.com/articles/announcing-the-new-euruko-workshop</guid>
    </item>
    <item>
      <title>How many tests are enough for this piece of code?</title>
      <description>&amp;lt;p&amp;gt;Let’s look at the following Ruby code, but it could be in any language, as the logic is more important than the actual code.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Screenshot of a simple Ruby code with one condition&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/how-many-tests-would-you-write-1.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I think of looking at the code and focusing on the line coverage, we can say that two tests might be enough.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Screenshot of a the two test cases that would cover line coverage&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/how-many-tests-would-you-write-2.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But this also might be misleading. We can see that if we want to test the entire truth table, then we need 4 test cases:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Screenshot of the 4 test cases that would cover the entire truth table&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/how-many-tests-would-you-write-3.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;There are various coverage criteria that we can apply and each one will result in a different number of test cases:&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;So how many tests do we need? 4 answers depending on our goal&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/how-many-tests-would-you-write-4.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;How do we choose between these coverage criteria?&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;We choose based on risk and project context.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Choosing criteria taking risk into consideration&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Choosing coverage criteria based on risk&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/how-many-tests-would-you-write-5.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;When talking about the risk, let’s use a simple graph having a Y axis going from low risk to high risk.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Branch coverage&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;In this case, for low risk, we have branch coverage. That is just making sure the entire decision (the entire expression used in the &amp;lt;code&amp;gt;if&amp;lt;/code&amp;gt; = &amp;lt;code&amp;gt;(A ||B)&amp;lt;/code&amp;gt;) is one time true and one time false. We could execute, for example, &amp;lt;code&amp;gt;A = true, B = does not matter&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;A = false, B = false&amp;lt;/code&amp;gt;, and that will achieve 100% branch coverage.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Condition Coverage&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Then, as the risk increases, we can apply condition coverage. That means ensuring that each independent condition (&amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt;) is both accurate and false. In this case, we need 2 test cases:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = false, B = true&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = true, B = false&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;You can notice that actually you might want to make also the decision (the entire IF) true and false so you might choose 3:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = true, B = does not matter&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = false, B = true&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = false, B = false&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;This is because of the short circuit logic that most programming languages have where if for example in case of &amp;lt;code&amp;gt;OR&amp;lt;/code&amp;gt; if the first condition is true, the other ones are not evaluated.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Modified Condition Decision Coverage&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The more the risk, the more we want to make sure to cover. In this case, we want to choose so that we can also check how each condition affects the decision.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;So we might choose the following test cases:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = false, B = false&amp;lt;/code&amp;gt; =&amp;gt; A is decisive and B is decisive&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = true, B = false&amp;lt;/code&amp;gt; =&amp;gt; A is decisive, B is not&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = false, B = true&amp;lt;/code&amp;gt; =&amp;gt; A is not decisive, B is decisive&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Truth table&amp;lt;/strong&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Of course if we want to cover all combinations, we have to make the entire truth table:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = true, B = false&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = true, B = true&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = false, B = false&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;code&amp;gt;A = false, B = true&amp;lt;/code&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;And this one will be choosen when the risk is high as we want to cover the possible logical cases here.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Choosing criteria, taking features or the project in consideration&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Choosing coverage criteria based on project or feature&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/how-many-tests-would-you-write-6.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Imagine that you are implementing a feature that is related to compliance with a standard or legal compliance.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;In this case, you should apply either a truth table or modified condition decision coverage as they have higher chances of catching more bugs and exercises more paths in your code.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But if you are working on something that is medium or low from the point of view of the end-users or clients, you might want to apply condition coverage or even just branch coverage.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Good Enough Testing means matching coverage to risk&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Summary of Good Enough Testing mindset&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/articles/how-many-tests-would-you-write-7.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;A core concept in Good Enough Testing is adapting to the risk and project context and choosing the test cases so that it lowers the risk and it covers what’s important in our project for the end-users, for the company and for the team.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;That means being systematic so we can rely on the test suite, focusing on what’s important to avoid overtesting or under-testing, and keeping it lean so the test suite is easy to maintain.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Don’t overtest.
Don’t guess.
Use structure.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2025-06-24</pubDate>
      <link>https://goodenoughtesting.com/articles/how-many-tests-would-you-write</link>
      <guid>https://goodenoughtesting.com/articles/how-many-tests-would-you-write</guid>
    </item>
    <item>
      <title>Tests should be simple</title>
      <description>&amp;lt;p&amp;gt;The &amp;lt;a href=&amp;quot;/&amp;quot;&amp;gt;Good Enough Workshops&amp;lt;/a&amp;gt; focus on creating the minimum number of test cases to ensure that the requirements, business logic, and code logic are adequately covered. So, during the workshops, we discuss how many tests are needed to cover a feature or piece of logic, how to reduce them when you don’t have time or in the context of the risk, and more related to test case design. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But we don’t talk about writing test code. There is a lot of information about how to write test code; there are good books and articles about this if you need a deep dive. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I am sharing my concise perspective on establishing a style guide or guidelines for writing tests in Minitest or RSpec. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;A screenshot of 5 principles for simple testing&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/tests-should-be-simple.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;1. Keep tests plain and simple&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Avoid complexity. A big part of avoiding complexity is avoiding abstractions in test code as much as possible. Don’t create abstractions with test code. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;You should write explicit, straightforward code. Focus on writing tests so that when read, they can fit in your mind in a single pass. There should not be a need to open other files or go back and forth between various sections in the same file. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Don&amp;rsquo;t try to be smart with your code. Don&amp;rsquo;t apply SOLID. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Test code should flow like a recipe from top to bottom.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;2. Each test should be read like a story&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;The story should describe clearly: &amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;preconditions&amp;lt;/strong&amp;gt; (state of the system before running the main action)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;the &amp;lt;strong&amp;gt;action&amp;lt;/strong&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;the &amp;lt;strong&amp;gt;expectation&amp;lt;/strong&amp;gt; or assertion&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;strong&amp;gt;postconditions&amp;lt;/strong&amp;gt; when needed (the state of the system after the test run)&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;When you need to write preconditions and postconditions, make sure the test will fail if they are not matched. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Example: &amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Use &amp;lt;code&amp;gt;create!&amp;lt;/code&amp;gt; instead of &amp;lt;code&amp;gt;create&amp;lt;/code&amp;gt; if you need to create AR&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Use &amp;lt;code&amp;gt;validate!&amp;lt;/code&amp;gt; on a new instance when you don&amp;rsquo;t want to create it &amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;h3&amp;gt;3. Having the same code across multiple tests is allowed and encouraged&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Duplicated code is allowed because it makes the system resilient to unintended changes.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Make the assertions explicit and, depending on the test’s purpose, assert them with concrete values rather than references to elements from the tested code. &amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;4. There should be positive and negative tests to limit the confirmation bias&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Make sure you have also written negative scenarios to cover the features/logic that you are testing. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;You should verify how your system handles invalid, unexpected, error-prone input or erroneous conditions. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Write at least one test that will cover the case where your feature/business logic should not work and will throw an error, return false/nil/empty &amp;hellip; &amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;5. Tests that never failed cannot be trusted&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;Consider that any tests that never fail cannot be trusted; thus, each test should have failed at least once on your computer before pushing the code.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;For each test, ensure you execute it at least once in a scenario where you have modified the code so that the test is expected to fail.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Don’t commit a test that never failed on your local machine. &amp;lt;/p&amp;gt;
</description>
      <pubDate>2024-11-20</pubDate>
      <link>https://goodenoughtesting.com/articles/tests-should-be-simple</link>
      <guid>https://goodenoughtesting.com/articles/tests-should-be-simple</guid>
    </item>
    <item>
      <title>Two new sessions for December 2024</title>
      <description>&amp;lt;p&amp;gt;I launched two new sessions of the workshop for December 2024:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;One session is scheduled for &amp;lt;a href=&amp;quot;https://lu.ma/zqp6zco1&amp;quot;&amp;gt;11 December 2024 - 08:00 UTC / 09:00 CET&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;The other for &amp;lt;a href=&amp;quot;https://lu.ma/533zg5zq&amp;quot;&amp;gt;12 December 2024 - 15:00 UTC / 16:00 CET / 10:00 EST&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;I choose two different times to accommodate more participants for the workshop. One slot is scheduled for morning Europe time, and the other for morning US time.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;This was requested by many people that wrote to me asking about different times for the workshop so more people can attend.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Pricing&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Based on the experience with the November workshops (&amp;lt;a href=&amp;quot;https://lu.ma/rx31g5h9&amp;quot;&amp;gt;session one&amp;lt;/a&amp;gt; and &amp;lt;a href=&amp;quot;https://lu.ma/hgs6eb3t&amp;quot;&amp;gt;session two&amp;lt;/a&amp;gt;) that were fully booked very quickly because there was a discount offered for joining earlier, I will continue with the Early Bird pricing for the ones in December.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The price for the December workshops is:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;USD 80 for anyone buying before 30 November&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;USD 100 for anyone buying after 30 November&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;h2&amp;gt;Workshop details&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;You can read more about the workshop on the &amp;lt;a href=&amp;quot;/#get-tickets&amp;quot;&amp;gt;homepage&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;And if you have any questions please &amp;lt;a href=&amp;quot;/contact&amp;quot;&amp;gt;contact me&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;
</description>
      <pubDate>2024-11-19</pubDate>
      <link>https://goodenoughtesting.com/articles/two-new-sessions-in-December-2024</link>
      <guid>https://goodenoughtesting.com/articles/two-new-sessions-in-December-2024</guid>
    </item>
    <item>
      <title>What is the difference between TDD and the testing process?</title>
      <description>&amp;lt;p&amp;gt;This is a question I sometimes receive, and I want to share my thoughts on it.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;TDD&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;TDD is a software development methodology that drives development through tests, facilitating the writing of code and building of features or products. Without doing here a full review of TDD, for this article we take the main idea that is about first writing tests and then writing the code that makes the tests pass. &amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Testing process&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;From a developer’s perspective, the testing process is a series of activities done to intentionally write tests with the purpose of verifying code correctness, documenting expected behavior, identifying defects or bugs, and improving maintainability.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;What is the difference?&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;First, while doing TDD you should write tests by using test design techniques which are part of the testing process.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Rather than viewing testing and development as two separate phases, consider that TDD involves writing tests so it will include applying testing activities while doing TDD.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Still, we talk about doing testing and doing TDD.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I think the main difference comes from what is called a development mindset and a testing mindset. This difference exists in both TDD methodology and in many others because it is about people and points of view while working.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Development mindset or developer mindset&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;While being in a development mindset, the focus is more on trying to write code that implements the requirements in
any form or shape they were provided. Thus the tests written while in the development mindset are more focused
on verifying requirements or proving that the code works as expected and requirements are met.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;From practice while being in development mindset there are more positive scenarios written than negative scenarios.
Keep in mind that it is considered positive scenario also when you are verifying for example than an API will return 404
when record not found. While this might be a failure from point of view of the user trying to access that page,
is a positive scenario because it tries to assess an expected behavior of the product.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The same goes for thinking about tests as documenting behavior. They will mostly be focused on the positive scenarios. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;There is also a bias there called developer bias. That means that once a solution is created
(either written, explained or thought about) the developer is more likely to write tests that are passing, thus
it is more inclined to demonstrate (with tests) that the code is working as expected or that the solution is the right one instead of trying to find the solution that solves the requirements. &amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Testing mindset or tester mindset&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;In the testing mindset, the focus is more on making sure the code is reliable, consistent predictable, and
it will not return unexpected results.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Thus, tests written while being in the testing mindset are focused more on edge cases of undocumented behavior; it is more
concerned with the questions &amp;ldquo;What happens if &amp;hellip;?&amp;rdquo; and &amp;ldquo;What happens when &amp;hellip;?&amp;rdquo;. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The tests written are mostly
negative scenarios, and so they are inspired by the idea of what could possibly trigger a bug.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;TDD and Testing Process&amp;lt;/h3&amp;gt;

&amp;lt;p&amp;gt;In the first phase of building a feature and applying TDD, we mostly live in the development mindset.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;That is both natural and good for making progress and being efficient as a developer. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;We want to first make the code work as expected with a focus more on the functional characteristics of the code and less on the
non-functional attributes (performance, security, &amp;hellip;). Less does not mean not paying attention to non-functional attributes while coding
but it is more about what kind of tests are written during this first phase.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Then, after the functional part of the requirements is implemented, we want to make sure the code is, for example:
reliable, consistent, predictable, maintainable, and performant. You can choose other non-functional/code quality attributes.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;During this second phase you can still use TDD (and if you are familiar with it, please do so) but the tests driving the development should
be generated while being in the testing mindset. Refactor the code to make these tests pass, thus improving the quality of the code.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;One trick for the testing mindset&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;One trick to switch to a testing mindset is to re-read the requirements, open a test file, think about what cases you want to test, and just write the names of the tests. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The tests will be higher quality if you write all of the cases first and then fill in the test code (preconditions, initial state, assertions) instead of writing the first test, run it, then write the second test, run it, and so on. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Whether we like it or not, writing test code is still development, and you will get back in the developer mindset before you get to think about what to test next. &amp;lt;/p&amp;gt;
</description>
      <pubDate>2024-10-24</pubDate>
      <link>https://goodenoughtesting.com/articles/difference-between-tdd-and-testing-activity</link>
      <guid>https://goodenoughtesting.com/articles/difference-between-tdd-and-testing-activity</guid>
    </item>
    <item>
      <title>How to think about testing as a developer</title>
      <description>&amp;lt;p&amp;gt;Here is the video version of this article:&amp;lt;/p&amp;gt;

&amp;lt;iframe src=&amp;quot;https://www.youtube.com/embed/b8wHuEufDAw&amp;quot; frameborder=&amp;quot;0&amp;quot; allow=&amp;quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&amp;quot; allowfullscreen class=&amp;quot;w-full aspect-w-16 aspect-h-9&amp;quot; height=&amp;quot;600&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;

&amp;lt;h2&amp;gt;High level view&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;In any project, there is an area called Quality Management that   has two main activities:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;Quality Assurance - mostly means measuring quality via various processes and tools either during the production and/or looking at the end result&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Quality Control - making sure we have processes in place that will guide, verify and change the organisation and in-place processes to assure a certain level of quality built-in&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;From this perspective, Testing is the outcome of a Quality Control decision and is an activity part of Quality Assurance.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;When doing side projects, for example, Quality Management is informal, and you mainly represent it. You decide (or not - but still a decision) what quality you want to have and how much, if anything, you want to do about it.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I will not go too deep into the Quality Management process, but it is good to know that testing is not just dropped into a project. Still, it should be part of a bigger strategy that looks into how much time/effort/money/people the organisation want to put in and how in order to get to a specific level of quality of our building process and the quality of our end result.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Let’s focus now on how developers should see testing and what can it bring to them.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;First, what is testing?&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;There are multiple definitions of testing.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Let me share some of them here for a good and informed starting point when considering testing and I will comment on them while trying to extract key points.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Making sure the software is predictable and consistent&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Software testing is a process, or a series of processes, designed to make sure computer code does what is designed to do and, conversely, that it does not anything unintended. Software should be predictable and consistent, presenting no surprises to users.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;cite&amp;gt; &amp;lt;a href=&amp;quot;#the-art-of-testing-reference&amp;quot;&amp;gt;Mayers, 2011&amp;lt;/a&amp;gt; &amp;lt;/cite&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I like this definition because it does not even use the words bugs, errors and we can focus more on what expectations we have from our code:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;To be predictable&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;To be consistent&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;To catch surprises or unexpected behavior&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Key point&amp;lt;/strong&amp;gt; &amp;lt;em&amp;gt;As a developer, I should assess if the execution of my code is predictable and consistent.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Key point&amp;lt;/strong&amp;gt; &amp;lt;em&amp;gt;As a developer, I should make sure that my code will only return expected outcomes/outputs and there should be no surprise.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Verifying the correctness of functionality and finding defects&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Testing is both a constructive activity in that it is verifying the correctness of functionality, and it may be a destructive activity in that the objective is to find defects in the implemented software. Testing verifies that the requirements are correctly implemented, and it yields the presence or absence of defects.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;cite&amp;gt; &amp;lt;a href=&amp;quot;#fundamentals-of-software-testing-reference&amp;quot;&amp;gt;O’Regan, 2019&amp;lt;/a&amp;gt; &amp;lt;/cite&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Key point&amp;lt;/strong&amp;gt; &amp;lt;em&amp;gt;As a developer I should verify that requirements are implemented&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Key point&amp;lt;/strong&amp;gt; &amp;lt;em&amp;gt;As a developer, I should check that there are no hidden bugs or cases improperly handled by my code by testing invalid or out-of-boundary inputs, logic, or state&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The “destructive activity” part is a good point of view to keep in mind while writing tests and could drive the effort also to execute/find test cases that might break the code/logic/app.&amp;lt;/p&amp;gt;

&amp;lt;h3&amp;gt;Comparing what-is with what-ought-to-be&amp;lt;/h3&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;At its core, testing is the process of comparing &amp;ldquo;what is&amp;rdquo; with &amp;ldquo;what ought to be.&amp;rdquo;&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;cite&amp;gt; &amp;lt;a href=&amp;quot;#a-practitioners-guide-reference&amp;quot;&amp;gt;Copeland, L. (2003)&amp;lt;/a&amp;gt; &amp;lt;/cite&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;strong&amp;gt;Key point&amp;lt;/strong&amp;gt; &amp;lt;em&amp;gt;As a developer, I want to verify that what was requested is what I implemented =&amp;gt; my code works the way it is expected&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Why do we test?&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;Based on the definitions above (and many more), it is good to define testing from the perspective of developers.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;We test because we want to:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;Verify that requirements are implemented correctly (what was requested is what it was implemented)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Check that the software behaves predictable and consistent over time (taking the same inputs and initial state, it should give the same result every time)&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;Specify the current behavior to improve maintainability&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;h2&amp;gt;References&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a name=&amp;quot;the-art-of-testing-reference&amp;quot;&amp;gt;[Mayers, 2011]&amp;lt;/a&amp;gt; Glenford J. Myers, Corey Sandler, and Tom Badgett. 2011. The Art of Software Testing (3rd. ed.). Wiley Publishing. &amp;lt;a href=&amp;quot;https://onlinelibrary.wiley.com/doi/book/10.1002/9781119202486&amp;quot;&amp;gt;DOI 10.1002/9781119202486&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a name=&amp;quot;fundamentals-of-software-testing-reference&amp;quot;&amp;gt;[O’Regan, 2019]&amp;lt;/a&amp;gt; O&amp;#39;Regan, Gerard. “Fundamentals of Software Testing.” Concise Guide to Software Testing (2019).&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a name=&amp;quot;a-practitioners-guide-reference&amp;quot;&amp;gt;[Copeland, L. (2003)]&amp;lt;/a&amp;gt; Lee Copeland, A Practitioner’s Guide to Software Test design - ISBN:158053791x&amp;lt;/p&amp;gt;
</description>
      <pubDate>2024-10-24</pubDate>
      <link>https://goodenoughtesting.com/articles/how-to-think-about-testing-as-a-developer</link>
      <guid>https://goodenoughtesting.com/articles/how-to-think-about-testing-as-a-developer</guid>
    </item>
    <item>
      <title>Session scheduled for 1st November is fully booked.</title>
      <description>&amp;lt;p&amp;gt;🙏 The GoodEnoughTesting workshop session &amp;lt;a href=&amp;quot;https://lu.ma/hgs6eb3t&amp;quot;&amp;gt;planned for 1st November is now fully booked&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Good Enough Testing - fully booked&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/1st-november-good-enough-testing-fully-booked.webp&amp;quot; /&amp;gt;
For anyone that still wants to join, I just opened the registration for the next session - happening on 22 November.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;As I announced this workshop is at full price. If you join until 31 October you will get 20% discount&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Register at: &amp;lt;a href=&amp;quot;https://lu.ma/rx31g5h9&amp;quot;&amp;gt;https://lu.ma/rx31g5h9&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a href=&amp;quot;https://lu.ma/rx31g5h9&amp;quot;&amp;gt;&amp;lt;img alt=&amp;quot;Get 20% discount until 31 October&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/22-november-20-percent-discount.webp&amp;quot; /&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
</description>
      <pubDate>2024-10-24</pubDate>
      <link>https://goodenoughtesting.com/articles/news-fully-booked-1st-november</link>
      <guid>https://goodenoughtesting.com/articles/news-fully-booked-1st-november</guid>
    </item>
    <item>
      <title>A short video introduction</title>
      <description>&amp;lt;p&amp;gt;I created a short video to introduce the workshop and explain what questions I am going to help you answer during the the workshop.&amp;lt;/p&amp;gt;

&amp;lt;iframe src=&amp;quot;https://www.youtube.com/embed/YqhgqzzNRuc&amp;quot; frameborder=&amp;quot;0&amp;quot; allow=&amp;quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&amp;quot; allowfullscreen class=&amp;quot;w-full aspect-w-16 aspect-h-9&amp;quot; height=&amp;quot;600&amp;quot;&amp;gt;&amp;lt;/iframe&amp;gt;
</description>
      <pubDate>2024-10-23</pubDate>
      <link>https://goodenoughtesting.com/articles/what-is-this-workshop</link>
      <guid>https://goodenoughtesting.com/articles/what-is-this-workshop</guid>
    </item>
    <item>
      <title>What is good enough testing?</title>
      <description>&amp;lt;p&amp;gt;When I was trying to search for this website online and see how Google renders it, I discovered that &amp;lt;a href=&amp;quot;https://en.wikipedia.org/wiki/James_Marcus_Bach&amp;quot;&amp;gt;James Bach&amp;lt;/a&amp;gt; coined the term “Good Enough Testing” in &amp;lt;strong&amp;gt;1998&amp;lt;/strong&amp;gt;.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I know about James Bach from teaching Exploratory testing techniques when I delivered the Certified ISTQB Foundation Level course so I think it is important to review the paper he published and see if there is something that I can use in my workshop.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;James’ paper &amp;lt;a href=&amp;quot;https://www.satisfice.com/download/a-framework-for-good-enough-testing&amp;quot;&amp;gt;available online at James’ website&amp;lt;/a&amp;gt; sets an excellent base for thinking about Good Enough Testing.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;What is Good Enough Testing?&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;He shares there the following definition for Good Enough Testing:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Good Enough testing is the process of developing a sufficient assessment of quality, at a reasonable cost, to enable wise and timely decisions to be made concerning the product.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;cite&amp;gt; &amp;lt;a href=&amp;quot;#james-back-reference&amp;quot;&amp;gt;James Bach. 1998&amp;lt;/a&amp;gt; &amp;lt;/cite&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I agree strongly with the definition; it feels more explicit than mine.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The definition I use in the workshop is the following:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Considering the level of risk, we define coverage criteria that will drive the test design so that we can achieve 100% coverage with the minimum number of test cases.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Definition of Good Enough Testing&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/what_is_good_enough_testing_max_1600.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;My workshops are focused on developers, and I try to show a series of tools or test design techniques that they can pick and use depending on the feature, the risk, and the time. I talked about the time axis in the workshop, but I see it closely connected with the risk.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The main idea is that we can use systematic test design techniques, and based on the level of risk and/or time constraints, we can apply the techniques, strict or loose. We can choose the maximum coverage or pick a coverage criteria that fits the current context.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The second point is that my workshop is dedicated to developers starting from the assumption that the purpose of testing in their specific case is:&amp;lt;/p&amp;gt;

&amp;lt;ul&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;To verify that the code works as expected&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;To document the code behavior&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;

&amp;lt;p&amp;gt;There are also other important objectives for testing (like finding bugs and validating that the solution is helping the end-user), but I think those first 2 are closer to developers and a good fit to get started.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I plan to create a very concrete and practical workshop, so I will continue to use my own due to the nature of the workshop.
There is not enough time to discuss how each part of the context can drive the testing and influence objectives, techniques, and execution. But I will definitely present and talk a bit also about James’ one.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Basic questions&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;In my workshop, I start with some questions that will drive what we learn:&amp;lt;/p&amp;gt;

&amp;lt;ol&amp;gt;
&amp;lt;li&amp;gt;How do you know how many tests are enough?&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;How do you know if your tests cover enough business logic?&amp;lt;/li&amp;gt;
&amp;lt;li&amp;gt;How confident are you that your tests cover the critical parts of your code?&amp;lt;/li&amp;gt;
&amp;lt;/ol&amp;gt;

&amp;lt;p&amp;gt;And the main idea is that we want to have a systematic approach to answering them.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;A systematic approach means finding a repeatable process or heuristic that does not depend on the developer’s experience. We want to predict the total number of test cases and ensure we can always identify and explain the current criteria.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;In the same paper “A Framework for Good Enough Testing”, James  starts with the following fundamental question:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;How do I know if I’m doing, or have done, enough of the right type of testing?&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;cite&amp;gt; &amp;lt;a href=&amp;quot;#james-back-reference&amp;quot;&amp;gt;James Bach. 1998&amp;lt;/a&amp;gt; &amp;lt;/cite&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;He adds more questions that will help assess the value of the testing:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;How accurate and complete is it?
How reasonable is it? Is it within project constraints? Is there a good return on investment, such as the extent of information gained per test?
How well does the assessment serve the project and the business?
Is it soon enough to be useful?&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;cite&amp;gt; &amp;lt;a href=&amp;quot;#james-back-reference&amp;quot;&amp;gt;James Bach. 1998&amp;lt;/a&amp;gt; &amp;lt;/cite&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;These are very useful questions to consider and would help create a testing strategy. James&amp;rsquo; chapter &amp;ldquo;Components of Assessment&amp;rdquo; covers various aspects of the product, testing costs, decision-making, and timing and in case you are preparing a testing strategy or a document about how to adapt testing to various project realities, I invite you to read it and try to answer all those questions.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;How to answer all these questions about testing&amp;lt;/h2&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;Unfortunately, there is no objective or rigorous calculus for answering this question, but we can identify what to consider in attempting to answer it. We can begin to build at least a heuristic framework around the problem.&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;cite&amp;gt; &amp;lt;a href=&amp;quot;#james-back-reference&amp;quot;&amp;gt;James Bach. 1998&amp;lt;/a&amp;gt; &amp;lt;/cite&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I agree that it is hard to create a generally applicable or objective way to answer these questions for all projects and contexts and this is why I narrowed down my focus in the workshop to help developers have a couple of test design techniques and teach them how to use and adapt them when trying to test their own code.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;While not enough to ensure good quality, it could be - in case of an engineering or development department - the base or starting point of good-quality product engineering. It provides the foundation for developing stronger and more user-focused quality processes for such department.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;References&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;a name=&amp;quot;james-back-reference&amp;quot;&amp;gt;[James Back, 1998]&amp;lt;/a&amp;gt; A Framework for Good Enough Testing. Computer 31, 10 (October 1998), 124–126. &amp;lt;a href=&amp;quot;https://doi.org/10.1109/2.722304&amp;quot;&amp;gt;https://doi.org/10.1109/2.722304&amp;lt;/a&amp;gt; - Full PDF available at &amp;lt;a href=&amp;quot;https://www.satisfice.com/download/a-framework-for-good-enough-testing&amp;quot;&amp;gt;satisfice.com&amp;lt;/a&amp;gt;&amp;lt;/p&amp;gt;
</description>
      <pubDate>2024-09-24</pubDate>
      <link>https://goodenoughtesting.com/articles/what-is-good-enough-testing</link>
      <guid>https://goodenoughtesting.com/articles/what-is-good-enough-testing</guid>
    </item>
    <item>
      <title>Announcing the Good Enough Workshops</title>
      <description>&amp;lt;p&amp;gt;A while back, I submitted a proposal for a talk or workshop at the &amp;lt;a href=&amp;quot;https://2024.euruko.org&amp;quot;&amp;gt;EuRuKo&amp;lt;/a&amp;gt; conference.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Here is what I wrote in the abstract where I described the workshop:&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;When learning Ruby or Ruby on Rails, you learn about RSpec or Minitest, you get to know the DSL and how to use the library features to write model, controller, or integration tests.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;But you don&amp;rsquo;t learn much about testing: What does it mean to test a feature or a piece of code? How do you know that the tests you wrote will actually catch bugs? &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;This talk is about test design techniques that help you write the minimum number of tests covering the widest surface of your app. You will learn about Decision Tables, Boundary Value Analysis, Equivalence Partitioning, State Transition testing and more, all with Ruby code examples. &amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;And as the main pitch I wrote: &amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;There are a lot of resources out there about how to write RSpec or Minitest and about speeding up test case execution, but there is precious little knowledge shared online about how to decide what to test and how to write a good test case in Ruby. This talk plans to close this knowledge gap by showing easy-to-use and practical test design techniques applied in Ruby and Ruby on Rails.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I have worked with Ruby since 2007 and am passionate about learning and teaching. I have over 11 of experience delivering technical training/workshops for teams on learning Ruby or testing. I am also an ISTQB-certified trainer, delivering international courses about testing to a wide range of audiences.**&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;Along with this workshop I also submitted a talk called “The Modern Rubyist.”&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;A response&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;To my complete surprise, I got a response from EuRuKo organizers that both my proposals were accepted by the program committee. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;And because both of them were subjects I was passionate about I decided to accept the challenge and deliver both of them.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;Early feedback&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;EuRuKo happened in September 2024, so I started working on the workshop around the end of July. I somehow had a version ready 2 weeks before the conference, and I wanted to test it and get some honest feedback. That is because the workshop supposed to be 2 hours and so I wanted to make sure that I manage to deliver some practical tips about how to test. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I though the best way to see the value of this workshop is to organise an online live version thus, I created one. I opened it for 10 participants because I wanted to make sure I have time to ask for feedback: &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;The first workshop session&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/first-session.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I thought about putting a price or not on it, but I decided to price it for 20 USD as the first session. I learned that when a workshop has a price, the participants are more focused and give honest feedback. If it is not helpful, you can find out very quickly. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;It sold in less than 24 hours and was the first hint that this might be useful&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I also got some very good feedback. Here is a part of it (but I will add more in one of the pages of the website)&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;img alt=&amp;quot;Feedback about the workshop&amp;quot; src=&amp;quot;https://images.goodenoughtesting.com/workshop-feedback.webp&amp;quot; /&amp;gt;&amp;lt;/p&amp;gt;

&amp;lt;blockquote&amp;gt;
&amp;lt;p&amp;gt;“Lucian&amp;rsquo;s understanding of the whole, the experience is noticeable and the demonstrations were smooth”&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;“Seeing the same testing strategies in various forms: drawings, tables, test files, graphs, etc. I like when I can view something differently, it helps to find blind spots”&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;“The content was great!  I had not seen actual definitions for some of the techniques that were presented!”&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;“The delivery, the way you presented it - not arrogant at all; like we are colleagues, you researched a topic and we hop on a call to help me understand it!”&amp;lt;/p&amp;gt;
&amp;lt;/blockquote&amp;gt;

&amp;lt;p&amp;gt;I also got more practical and valuable feedback and so I was prepared for the EuRuKo workshop. &amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;EuRuKo workshop&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;At EuRuKo I found out that the workshop was fully booked. We discussed over email one week before the workshop, and I agreed to a maximum of 50 participants because I wanted to make it a bit more interactive. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;And all seats were booked before the conference started. That put a bit of pressure on me. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;I delivered the workshop, and had a great interaction with the participants, and I will publish the video here because it was recorded. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;Of course having 50 participants makes the workshop be more toward me explaining the techniques and we did not had enough time to write the actual tests in Minitest/Rspec. Anyhow as the workshop is more about the how to design test cases than how to write in Minitest or RSpec this worked out well.&amp;lt;/p&amp;gt;

&amp;lt;h2&amp;gt;More sessions&amp;lt;/h2&amp;gt;

&amp;lt;p&amp;gt;I think learning how to design better test cases is important and so I will launch a series of live workshops. I will increase the time to &amp;lt;strong&amp;gt;3 hours per workshop&amp;lt;/strong&amp;gt; and probably a maximum 15 participants per session. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;The price will also be increased step by step until it reaches 100 USD per workshop. I think 100 USD is a good enough price to ensure everyone is involved, and I think this is the value that people could get out of my workshop.&amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If you, as a participant, are able to save 2-3 hours while writing tests at your job next week after my workshop, or if writing better tests improves the quality of your code, I think this would make paying for the workshop a no-brainer. &amp;lt;/p&amp;gt;

&amp;lt;p&amp;gt;If you like this idea, subscribe to the newsletter 👇 &amp;lt;/p&amp;gt;
</description>
      <pubDate>2024-09-22</pubDate>
      <link>https://goodenoughtesting.com/articles/website-launch</link>
      <guid>https://goodenoughtesting.com/articles/website-launch</guid>
    </item>
  </channel>
</rss>
