<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Augusto Hubert</title>
    <description>The latest articles on Forem by Augusto Hubert (@augustohub-br).</description>
    <link>https://forem.com/augustohub-br</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3556512%2Ffb8ccf92-c7f0-4274-a703-415dc2ffe1f9.png</url>
      <title>Forem: Augusto Hubert</title>
      <link>https://forem.com/augustohub-br</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/augustohub-br"/>
    <language>en</language>
    <item>
      <title>Organizing Tests with Clarity: the Unfolding Tests Technique</title>
      <dc:creator>Augusto Hubert</dc:creator>
      <pubDate>Thu, 09 Oct 2025 16:13:43 +0000</pubDate>
      <link>https://forem.com/augustohub-br/organizing-tests-with-clarity-the-unfolding-tests-technique-195d</link>
      <guid>https://forem.com/augustohub-br/organizing-tests-with-clarity-the-unfolding-tests-technique-195d</guid>
      <description>&lt;p&gt;&lt;em&gt;[pt-BR] Existe uma versão desse artigo em pt-BR, que você pode acessar &lt;a href="https://dev.to/augustohub-br/pt-br-organizando-testes-com-clareza-a-tecnica-do-unfolding-tests-26d3"&gt;aqui&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In recent years, much of my work has involved helping teams expand and optimize their automated test suites. And one thing that comes up repeatedly is the same kind of problem: the tests exist, but they are hard to understand.&lt;/p&gt;

&lt;p&gt;No one knows exactly what is being tested, where certain scenarios are, or whether the logical branches are truly covered. As a result, you see coverage gaps, redundant tests, and a lot of time wasted trying to understand what already exists.&lt;/p&gt;

&lt;p&gt;On many occasions, when pairing with less experienced developers, I notice a recurring pattern: they spend a long time scrolling up and down the test file, looking for code that looks “similar” to what they want to write. The idea is to place the new test “near the other similar ones.” This habit is understandable, but it’s also a symptom of a structural problem: if you need to “guess” where the test should go, the file structure isn’t clear enough.&lt;/p&gt;

&lt;p&gt;Over time, I developed a technique that helps me organize and visualize test structures. It’s simple and practical, and it leverages a feature that almost every modern text editor has: &lt;strong&gt;code folding&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I call this technique &lt;strong&gt;Unfolding Tests&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The examples in this article use Ruby on Rails and RSpec, but the same principles apply to any other testing framework.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The idea behind Unfolding Tests
&lt;/h2&gt;

&lt;p&gt;The idea is to use code block folding as both a reading and writing tool. In VS Code, for example, you can fold and unfold blocks such as &lt;code&gt;describe&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt;, and &lt;code&gt;it&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To start, use the &lt;strong&gt;Fold All&lt;/strong&gt; command (on macOS: Cmd + Shift + P; on Windows: Ctrl + Shift + P) and type “Fold All.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This technique is grounded in the idea of &lt;strong&gt;reducing cognitive load&lt;/strong&gt;. When everything is folded, you see only the skeleton of the test, which lets you quickly understand what’s being tested and how the scenarios are organized, without reading the implementation details. That way, the focus becomes the &lt;strong&gt;intent&lt;/strong&gt;, rather than every line of code.&lt;/p&gt;

&lt;p&gt;From there, I gradually expand the blocks and come to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What’s being tested (&lt;code&gt;describe&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;What the possible scenarios are (&lt;code&gt;context&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;What the expectations are in each scenario (&lt;code&gt;it&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;And which setups are used at each level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hierarchical view provides a much clearer reading of the system’s behavior under test. What’s most interesting is that the same process also works when writing tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Writing tests
&lt;/h2&gt;

&lt;p&gt;When I start a new test file, I don’t think in lines of code. &lt;strong&gt;I think in the structure I want to see when folded.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, I create the skeleton of the test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;UserPolicy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when user is admin'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'allows access'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when user is not admin'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'denies access'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When that file is fully folded, what I see is something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UserPolicy
  when user is admin
    allows access
  when user is not admin
    denies access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is already enough to understand what’s being tested and what the scenarios are.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By the way, this view is very similar to the &lt;a href="https://rspec.info/features/3-13/rspec-core/command-line/format-option/" rel="noopener noreferrer"&gt;RSpec output when you use the --format documentation option&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you’re not using that format yet, you should. It turns test execution into an almost narrative reading, showing exactly what each test describes, in the same hierarchy you defined in the &lt;code&gt;describe&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt;, and &lt;code&gt;it&lt;/code&gt; blocks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After that, I unfold block by block and fill in the details: setups, mocks, expectations, and so on.&lt;/p&gt;




&lt;h2&gt;
  
  
  The hierarchy of setups
&lt;/h2&gt;

&lt;p&gt;One of the most important parts of Unfolding Tests is respecting the hierarchy between the blocks and their setups.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under each &lt;code&gt;describe&lt;/code&gt;, there should be a setup with the general prerequisites for all scenarios inside that block.&lt;/li&gt;
&lt;li&gt;Under each &lt;code&gt;context&lt;/code&gt;, there should be a setup with the prerequisites specific to that scenario. Your setup here must provide the conditions that make the &lt;code&gt;context&lt;/code&gt; description true.&lt;/li&gt;
&lt;li&gt;The test code itself should always be inside the &lt;code&gt;it&lt;/code&gt; block, which is the lowest level in the structure where expectations are verified.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'Listing orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admin_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;sign_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;visit&lt;/span&gt; &lt;span class="n"&gt;orders_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when there are no orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete_all&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'shows the empty state message'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'No orders found'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when there are orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:orders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'lists all orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;and&lt;/span&gt; &lt;span class="n"&gt;have_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you fold this file, even without seeing the implementation details, you can understand the purpose of the test, the scenarios it covers, and the expected behavior in each case. Then, when you unfold each block, you reveal the necessary details: first the setup, then the test.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contexts as logical branches
&lt;/h2&gt;

&lt;p&gt;An important principle of this technique is that each logical branch deserves its own &lt;code&gt;context&lt;/code&gt;. If a variable can take three states (for example, &lt;code&gt;full&lt;/code&gt;, &lt;code&gt;partial&lt;/code&gt;, &lt;code&gt;empty&lt;/code&gt;), then you should have three contexts, one for each case.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when report is full'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when report is partial'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when report is empty'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps ensure that the tests truly explore all relevant possibilities.&lt;/p&gt;

&lt;p&gt;And more: to me, it doesn’t make sense to have a context without others that represent opposing states. If there’s a &lt;code&gt;context 'when user is admin'&lt;/code&gt;, there should also be a &lt;code&gt;context 'when user is not admin'&lt;/code&gt;. These pairs make it clear that the test covers both sides of the logic, and that’s easy to see when the file is folded.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why this works
&lt;/h2&gt;

&lt;p&gt;Unfolding Tests turns the act of reading and writing tests into something visual and incremental.&lt;br&gt;
You see the structure before you see the details, which helps you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quickly understand the scope of the file&lt;/li&gt;
&lt;li&gt;Identify redundancies and gaps&lt;/li&gt;
&lt;li&gt;Ensure that each logical path has its counterpart&lt;/li&gt;
&lt;li&gt;Write tests that also serve as living documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, &lt;strong&gt;a good test is also a good form of documentation&lt;/strong&gt;. And the clearer the intent expressed in the structure, the easier it will be for anyone to understand the expected behavior of the system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Tips to start applying
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fold everything (&lt;code&gt;Fold All&lt;/code&gt;).&lt;/strong&gt;&lt;br&gt;
Start with the test file completely folded. This gives you a clear overview of the structure, the main blocks, and the existing scenarios.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unfold gradually.&lt;/strong&gt;&lt;br&gt;
Expand the outer &lt;code&gt;describe&lt;/code&gt; blocks first to understand what’s being tested. Then open the &lt;code&gt;context&lt;/code&gt; blocks to see the scenarios, and finally the &lt;code&gt;it&lt;/code&gt; blocks to look at the expectations. This gradual progression helps you understand the test layer by layer, without overloading your mind with unnecessary details right away.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check if the structure makes sense when folded.&lt;/strong&gt;&lt;br&gt;
If, with everything folded, you can’t tell what the file is testing or which scenarios it covers, that’s a sign the structure needs to be revisited.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;When writing new tests, think about the structure first.&lt;/strong&gt;&lt;br&gt;
Build the skeleton with &lt;code&gt;describe&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt;, and &lt;code&gt;it&lt;/code&gt; before writing any code.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;context&lt;/code&gt; to express logical variations.&lt;/strong&gt;&lt;br&gt;
Whenever possible, write contexts in pairs — for example, “when user is admin” and “when user is not admin.”  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Respect the setup hierarchy.&lt;/strong&gt;&lt;br&gt;
Place general &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;let&lt;/code&gt; definitions inside the &lt;code&gt;describe&lt;/code&gt;, and specific setups inside each &lt;code&gt;context&lt;/code&gt;.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Only then write the test code (&lt;code&gt;it&lt;/code&gt;).&lt;/strong&gt;&lt;br&gt;
Once the structure and prerequisites are clear, add the actual test code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Unfolding Tests is a simple way to bring clarity and intent to your tests.&lt;/p&gt;

&lt;p&gt;It forces you to think about structure before details and to treat each scenario as part of a cohesive whole. In the end, the benefit is twofold: tests become easier to understand, and the code is less likely to get lost among confusing or redundant cases.&lt;/p&gt;

&lt;p&gt;If you often get lost in large test files, try folding everything and then unfolding gradually. It’s a very simple technique, yet it’s impressive how much it changes the way you read and write tests.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>testing</category>
      <category>rails</category>
    </item>
    <item>
      <title>Organizando testes com clareza: a técnica do Unfolding Tests</title>
      <dc:creator>Augusto Hubert</dc:creator>
      <pubDate>Thu, 09 Oct 2025 16:12:50 +0000</pubDate>
      <link>https://forem.com/augustohub-br/pt-br-organizando-testes-com-clareza-a-tecnica-do-unfolding-tests-26d3</link>
      <guid>https://forem.com/augustohub-br/pt-br-organizando-testes-com-clareza-a-tecnica-do-unfolding-tests-26d3</guid>
      <description>&lt;p&gt;&lt;em&gt;[EN] There is a version of this article in english, you can access it &lt;a href="https://dev.to/augustohub-br/organizing-tests-with-clarity-the-unfolding-tests-technique-195d"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Nos últimos anos, grande parte do meu trabalho tem sido ajudar times a ampliar e otimizar suas suítes de testes automatizados. E uma coisa que se repete o tempo todo é o mesmo tipo de problema: os testes até existem, mas são difíceis de entender.&lt;/p&gt;

&lt;p&gt;Ninguém sabe exatamente o que está sendo testado, onde estão certos cenários ou se as ramificações lógicas estão realmente cobertas. Como resultado, aparecem buracos de cobertura, testes redundantes e muito tempo perdido tentando entender o que já existe.&lt;/p&gt;

&lt;p&gt;Em diversas ocasiões, ao parear com desenvolvedores menos experientes, vejo um padrão se repetir: eles passam um bom tempo rolando o arquivo de testes de cima a baixo, procurando por um código “parecido” com o que querem escrever. A ideia é colocar o novo teste “perto dos outros semelhantes”. Esse hábito é compreensível, mas também um sintoma de um problema estrutural: se você precisa "adivinhar" onde o teste deveria estar, é porque a estrutura do arquivo não está clara o suficiente.&lt;/p&gt;

&lt;p&gt;Com o tempo, desenvolvi uma técnica que me ajuda bastante a organizar e visualizar a estrutura dos testes. É simples, prática e aproveita um recurso que praticamente todo editor de texto moderno tem: &lt;strong&gt;o folding de código&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Eu chamo essa técnica de &lt;strong&gt;Unfolding Tests&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Os exemplos que aparecem neste artigo usam Ruby on Rails e RSpec, mas os mesmos princípios se aplicam a qualquer outro framework de testes.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  A ideia por trás do Unfolding Tests
&lt;/h2&gt;

&lt;p&gt;A ideia é usar o “folding” de blocos de código como uma ferramenta de leitura e escrita. No VSCode, por exemplo, você pode dobrar (fold) e desdobrar (unfold) blocos de código como describe, context e it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Para começar, basta usar o comando Fold All (no macOS: Cmd + Shift + P; no Windows: Ctrl + Shift + P) e digitar “Fold All”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essa técnica vem muito da ideia de &lt;strong&gt;reduzir a carga cognitiva&lt;/strong&gt;. Quando tudo está dobrado, você vê apenas o esqueleto do teste, o que permite entender rapidamente o que está sendo testado e como os cenários estão organizados, sem precisar ler detalhes de implementação.&lt;/p&gt;

&lt;p&gt;Com isso, o foco passa a ser principalmente a &lt;strong&gt;INTENÇÃO&lt;/strong&gt;, e não cada linha de código.&lt;/p&gt;

&lt;p&gt;A partir daí, começo a expandir os blocos aos poucos e com isso passo a entender:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O que está sendo testado (&lt;code&gt;describe&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Quais são os cenários possíveis (&lt;code&gt;context&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Quais são as expectativas em cada cenário (&lt;code&gt;it&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;E quais setups estão sendo usados em cada camada&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essa visão hierárquica me dá uma leitura muito mais clara do comportamento do sistema testado. E o mais interessante é que o mesmo processo funciona também para escrever testes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Escrevendo testes com Unfolding Tests
&lt;/h2&gt;

&lt;p&gt;Quando começo um novo arquivo de testes, eu não penso nas linhas de código. &lt;strong&gt;Penso na estrutura que quero ver dobrada&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Crio primeiro o esqueleto do teste:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;RSpec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt; &lt;span class="no"&gt;UserPolicy&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when user is admin'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'allows access'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when user is not admin'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'denies access'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando esse arquivo está totalmente dobrado, o que vejo é algo como:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UserPolicy
  when user is admin
    allows access
  when user is not admin
    denies access
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso já é suficiente para entender o que está sendo testado e quais são os cenários.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Aliás, essa visualização lembra bastante o &lt;a href="https://rspec.info/features/3-13/rspec-core/command-line/format-option/" rel="noopener noreferrer"&gt;output do RSpec quando você usa o formato --format documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Se você ainda não está usando esse formato, deveria. Ele transforma a execução dos testes em uma leitura quase narrativa, mostrando exatamente o que cada teste descreve, na mesma hierarquia que você definiu nos blocos describe, context e it.&lt;/p&gt;

&lt;p&gt;Depois disso, vou desdobrando bloco por bloco e preenchendo os detalhes: setups, mocks, expectations e assim por diante.&lt;/p&gt;




&lt;h2&gt;
  
  
  A hierarquia de setups
&lt;/h2&gt;

&lt;p&gt;Uma das partes mais importantes do Unfolding Tests é respeitar a hierarquia entre os blocos e seus setups.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Abaixo de cada &lt;code&gt;describe&lt;/code&gt; deve haver um setup com os pré-requisitos gerais para todos os cenários que estão dentro daquele bloco.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Abaixo de cada &lt;code&gt;context&lt;/code&gt; deve haver um setup com os pré-requisitos específicos daquele cenário. Aqui seu setup deve prover as condições para que a descrição do seu &lt;code&gt;context&lt;/code&gt; seja verdadeira.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;E o código do teste em si deve estar sempre dentro do bloco &lt;code&gt;it&lt;/code&gt;, que é o nível mais baixo da estrutura, onde as expectativas são verificadas.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;describe&lt;/span&gt; &lt;span class="s1"&gt;'Listing orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;let&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:admin_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:admin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;sign_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;admin_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;visit&lt;/span&gt; &lt;span class="n"&gt;orders_path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when there are no orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete_all&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'shows the empty state message'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'No orders found'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when there are orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;let!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:orders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;create_list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s1"&gt;'lists all orders'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;have_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;and&lt;/span&gt; &lt;span class="n"&gt;have_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se você dobrar esse arquivo, mesmo sem ver os detalhes de implementação do teste, dá para entender o propósito do teste, os cenários que ele cobre e o comportamento esperado em cada caso. E então, ao desdobrar cada bloco, você revela os detalhes necessários: primeiro o setup, depois o teste.&lt;/p&gt;




&lt;h2&gt;
  
  
  Contexts como ramificações lógicas
&lt;/h2&gt;

&lt;p&gt;Um princípio importante dessa técnica é que cada ramificação lógica merece o seu próprio &lt;code&gt;context&lt;/code&gt;.Se uma variável pode assumir três estados (Ex. &lt;code&gt;full&lt;/code&gt;, &lt;code&gt;partial&lt;/code&gt;, &lt;code&gt;empty&lt;/code&gt;), então você deve ter três contexts, um para cada caso.&lt;/p&gt;

&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when report is full'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when report is partial'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="s1"&gt;'when report is empty'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="c1"&gt;# ...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso ajuda a garantir que os testes realmente explorem todas as possibilidades relevantes.&lt;/p&gt;

&lt;p&gt;E mais: para mim, não faz sentido ter um context sem outros que representam outros estados antagonistas. Se existe um context 'when user is admin', então precisa existir outro context 'when user is not admin'. Esses pares deixam claro que o teste cobre ambos os lados da lógica, e isso é fácil de perceber quando o arquivo está dobrado.&lt;/p&gt;




&lt;h2&gt;
  
  
  Por que isso funciona
&lt;/h2&gt;

&lt;p&gt;O Unfolding Tests transforma o ato de ler e escrever testes em algo visual e incremental.&lt;br&gt;
Você vê a estrutura antes de ver os detalhes, o que ajuda a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entender rapidamente o escopo do arquivo&lt;/li&gt;
&lt;li&gt;Identificar redundâncias e lacunas&lt;/li&gt;
&lt;li&gt;Garantir que cada caminho lógico tem seu par&lt;/li&gt;
&lt;li&gt;Escrever testes que também servem como documentação viva&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No fim das contas, u*&lt;em&gt;m bom teste é também uma boa forma de documentação&lt;/em&gt;*. E quanto mais clara for a intenção expressa na estrutura, mais fácil será para qualquer pessoa entender o comportamento esperado do sistema.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dicas para começar a aplicar
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dobre tudo (&lt;code&gt;Fold All&lt;/code&gt;).&lt;/strong&gt;&lt;br&gt;
Comece com o arquivo de testes completamente dobrado. Isso te dá uma visão geral da estrutura, dos blocos principais e dos cenários existentes.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vá desdobrando gradualmente.&lt;/strong&gt;&lt;br&gt;
Expanda primeiro os blocos &lt;code&gt;describe&lt;/code&gt; para entender o que está sendo testado. Depois abra os &lt;code&gt;context&lt;/code&gt; para ver os cenários e, por fim, os &lt;code&gt;it&lt;/code&gt; para olhar as expectativas. Essa progressão te permite entender o teste camada por camada, sem sobrecarregar a mente com detalhes desnecessários logo de início.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Verifique se a estrutura faz sentido dobrada.&lt;/strong&gt;&lt;br&gt;
Se, com tudo dobrado, você não consegue entender o que o arquivo testa ou quais cenários cobre, é sinal de que a estrutura precisa ser revista.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ao escrever novos testes, pense primeiro na estrutura.&lt;/strong&gt;&lt;br&gt;
Monte o esqueleto com &lt;code&gt;describe&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt; e &lt;code&gt;it&lt;/code&gt; antes de escrever o código.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Use &lt;code&gt;context&lt;/code&gt; para expressar variações lógicas.&lt;/strong&gt;&lt;br&gt;
Sempre que possível, escreva contexts em pares — por exemplo, “when user is admin” e “when user is not admin”.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Respeite a hierarquia dos setups.&lt;/strong&gt;&lt;br&gt;
Use o &lt;code&gt;before&lt;/code&gt; e o &lt;code&gt;let&lt;/code&gt; geral dentro do &lt;code&gt;describe&lt;/code&gt;, e setups específicos dentro de cada &lt;code&gt;context&lt;/code&gt;.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Só então escreva o conteúdo dos testes (&lt;code&gt;it&lt;/code&gt;).&lt;/strong&gt;&lt;br&gt;
Depois que a estrutura e os pré-requisitos estiverem claros, adicione o código do teste em si.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;O Unfolding Tests é uma forma simples de trazer clareza e intenção para os testes.&lt;/p&gt;

&lt;p&gt;Ele força você a pensar na estrutura antes dos detalhes e a tratar cada cenário como parte de um todo coeso. No fim, o benefício é duplo: os testes ficam mais fáceis de entender e o código fica mais difícil de se perder em meio a casos confusos ou redundantes.&lt;/p&gt;

&lt;p&gt;Se você costuma se perder em arquivos grandes de teste, experimente dobrar tudo e ir desdobrando aos poucos. É uma técnica muito simples mas é impressionante como isso muda a maneira de ler e escrever testes.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>rails</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
