<?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>DEV Community: Lucas Gabriel Sánchez</title>
    <description>The latest articles on DEV Community by Lucas Gabriel Sánchez (@unkiwii).</description>
    <link>https://dev.to/unkiwii</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%2F602519%2F9de15980-1f2e-40b4-b29c-12c812a20b75.png</url>
      <title>DEV Community: Lucas Gabriel Sánchez</title>
      <link>https://dev.to/unkiwii</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/unkiwii"/>
    <language>en</language>
    <item>
      <title>Who tests the tests?</title>
      <dc:creator>Lucas Gabriel Sánchez</dc:creator>
      <pubDate>Fri, 20 Feb 2026 17:05:58 +0000</pubDate>
      <link>https://dev.to/cloudx/who-tests-the-tests-nhc</link>
      <guid>https://dev.to/cloudx/who-tests-the-tests-nhc</guid>
      <description>&lt;p&gt;This post is based on a &lt;a href="https://www.gophercon.com/" rel="noopener noreferrer"&gt;Gophercon&lt;/a&gt; talk by &lt;a href="https://github.com/danicat" rel="noopener noreferrer"&gt;Daniela Petruzalek&lt;/a&gt;: &lt;a href="https://www.youtube.com/watch?v=av2f2okDOyk" rel="noopener noreferrer"&gt;Who tests the tests?&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A little bit of history
&lt;/h2&gt;

&lt;p&gt;In the beginning, we checked our code manually, running the application and trying different inputs: we called that manual testing. Then we discovered that we could write code to test application code to check if it's correct: we called that automatic testing (unit, integration, functional, etc.)&lt;/p&gt;

&lt;p&gt;Now we are in the AI era where we write fewer tests and even less code, we need a way to swiftly check that the tests are correct and that they are testing the cases we expect in our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can we know if code written by AI is correct?
&lt;/h2&gt;

&lt;p&gt;You can use automatic tests in the same way we used to check code written by humans.&lt;/p&gt;

&lt;p&gt;One option would be to let the AI write the application code and you write the tests, &lt;a href="https://dev.to/marabesi/ai-and-tdd-a-match-that-can-work-1d59"&gt;you can even use TDD&lt;/a&gt; where you, the human, write the tests and let the AI write the implementation after.&lt;/p&gt;

&lt;p&gt;Another option is to let the AI write the application code and the tests, but then how can you be sure that those tests are testing the things you want or need? Reading and understanding the tests would be the best, but can we do that automatically?&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter: mutation tests
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Mutation_testing" rel="noopener noreferrer"&gt;Mutation testing&lt;/a&gt; is a way to check that the tests you have are testing the code the way you want by making small changes to the application code and checking that the tests fail as expected.&lt;/p&gt;

&lt;p&gt;It's based on a concept known as a mutant: a version of your application with a small change.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;p&gt;The mutation testing cycle is this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a mutant: change the application code by applying just one change&lt;/li&gt;
&lt;li&gt;Run your test suite&lt;/li&gt;
&lt;li&gt;Check how many mutants were killed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After running your tests, the ones that failed are said to have killed the mutant, those tests are testing something related to the code you changed and are, from the perspective of that change, good tests.&lt;/p&gt;

&lt;p&gt;After many changes, if a test never failed it means that test didn't kill any mutant and is a weak test. You should probably delete that test or write a better one.&lt;/p&gt;

&lt;p&gt;If a mutant is never killed, then that code is not being tested (no coverage) or is being tested poorly, you have an opportunity to write a test to check that piece of code if needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I have to make these changes manually?
&lt;/h3&gt;

&lt;p&gt;You can do it manually, but there are some tools to aid you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;C#, TypeScript and Scala: &lt;a href="https://stryker-mutator.io/" rel="noopener noreferrer"&gt;Stryker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go: &lt;a href="https://github.com/go-gremlins/gremlins" rel="noopener noreferrer"&gt;go-gremlins&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Java: &lt;a href="https://pitest.org/" rel="noopener noreferrer"&gt;pitest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Python: &lt;a href="https://mutatest.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;mutatest&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Rust: &lt;a href="https://mutants.rs/welcome.html" rel="noopener noreferrer"&gt;mutants.rs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools provide a way to make those changes automatically and some of them run the tests for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do we need mutation testing?
&lt;/h2&gt;

&lt;p&gt;Let's see a very simple example in Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t divide by 0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simple test suite we can have is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;unittest&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;divide&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDivide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TestCase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_divide_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertRaises&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_divide_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;unittest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the tests and everything is fine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python tests.py
..
&lt;span class="nt"&gt;----------------------------------------------------------------------&lt;/span&gt;
Ran 2 tests &lt;span class="k"&gt;in &lt;/span&gt;0.000s

OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are testing both flows, when an error is raised and when we complete a successful operation, coverage is at 100% but those tests are not great, and here's why: let's change the implementation of divide from a/b to &lt;code&gt;a*b&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;can&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t divide by 0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the tests should fail, right? They don't, because &lt;code&gt;1*1&lt;/code&gt; is still 1:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python tests.py
..
&lt;span class="nt"&gt;----------------------------------------------------------------------&lt;/span&gt;
Ran 2 tests &lt;span class="k"&gt;in &lt;/span&gt;0.000s

OK
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a problematic test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_divide_success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assertEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;divide&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even when you have 100% test coverage, that doesn't mean you have 100% test case coverage; some cases may be missing or not being tested correctly.&lt;/p&gt;

&lt;p&gt;What we did here was a mutation: from &lt;code&gt;a/b&lt;/code&gt; to &lt;code&gt;a*b&lt;/code&gt;, that mutation gives us information about our tests that we didn't have before.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to read the results of mutation testing?
&lt;/h2&gt;

&lt;p&gt;When you run your test suite against mutated code, each test can do one of two things: &lt;em&gt;kill&lt;/em&gt; the mutant (the test fails, so it detected the change) or &lt;em&gt;survive&lt;/em&gt; (the test still passes, so it missed the change). After many mutation, you can summarize how often each test killed mutants, for example:&lt;/p&gt;

&lt;p&gt;After 200 Mutations:&lt;br&gt;
TestA: 140 Kills, 60 Survived&lt;br&gt;
TestB: 200 Kills&lt;br&gt;
TestC: 30 Kills, 170 Survived&lt;/p&gt;

&lt;p&gt;How to interpret this:&lt;/p&gt;

&lt;p&gt;TestA: is good test because on most mutations it was killed.&lt;br&gt;
TestB: is your strongest test, it detects every mutation you ran.&lt;br&gt;
TestC: is the weak one, it usually doesn't detect mutations.&lt;/p&gt;

&lt;h2&gt;
  
  
  When not to use mutation testing?
&lt;/h2&gt;

&lt;p&gt;In some projects or languages, running mutation tests can take hours. For each mutant, the tool has to compile (if needed) and run the full test suite. If your test suite takes 10 minutes, each mutation will take at least that long, so keep this in mind.&lt;/p&gt;

&lt;p&gt;Use this approach on small projects or ones where the "edit, compile, test" cycle is small.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;So who tests the tests? In practice, mutation testing does that: by checking that your tests react when the code is deliberately broken.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>go</category>
      <category>programming</category>
    </item>
    <item>
      <title>Why you should learn Go?</title>
      <dc:creator>Lucas Gabriel Sánchez</dc:creator>
      <pubDate>Tue, 06 Apr 2021 14:59:53 +0000</pubDate>
      <link>https://dev.to/cloudx/why-you-should-learn-go-3g0a</link>
      <guid>https://dev.to/cloudx/why-you-should-learn-go-3g0a</guid>
      <description>&lt;p&gt;I can already hear you: Another programming language? WHY?!&lt;/p&gt;

&lt;p&gt;There are already more than &lt;a href="https://en.wikipedia.org/wiki/List_of_programming_languages" rel="noopener noreferrer"&gt;650&lt;/a&gt; programming languages.&lt;/p&gt;

&lt;p&gt;Maybe you already know a few of them and can read and write one or two with great ease. Then if you can do X in Y programming language, why do you need to learn to do it in Go? To start answer that I will tell you a story, my story.&lt;/p&gt;

&lt;p&gt;When I began my journey to become a programmer I wanted to know: What were the languages used in the wild?. I only knew Visual Basic, but didn't have any clue that almost nobody was using it in production. After a few months I discovered one programming language was dominating: Java. At that point I set the goal to learn Java and so I did.&lt;/p&gt;

&lt;p&gt;I learned about object oriented programming and design patterns to understand Java. Also learned about classes and interfaces, about virtual methods and packages. The language was an excuse to learn a lot of theory about how to develop applications.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kb3hbabhnk8gjgoftcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0kb3hbabhnk8gjgoftcw.png" alt="The Go Programming Language"&gt;&lt;/a&gt;&lt;br&gt;
Since then I learned Pascal, Python, C, C++, C#, Erlang, ActionScript, JavaScript and Go. Every language had its own rules and quirks but a lot of them have the same principles and foundations. How many languages you know that use classes to define objects? How many languages use methods and the concept of "this" to refer to the object that receives the method call?&lt;/p&gt;

&lt;p&gt;Later, a wise programmer told me: "The only programming languages worth learning are the ones that can teach you something new". Some languages taught me something new, but not all of them. &lt;/p&gt;

&lt;p&gt;Some may say that learning Pascal or Erlang is not a good move in 2021, but they taught me things that I didn't know before.&lt;/p&gt;

&lt;p&gt;From Erlang I learned the philosophy of its creators: "fail fast and fail loud". To have a resilient system, you should fail fast and loud so other parts of the system can do something about it.&lt;/p&gt;

&lt;p&gt;From Python I learned that simple is better than complex. Explicit is better than implicit. &lt;a href="https://www.python.org/dev/peps/pep-0020/#id2" rel="noopener noreferrer"&gt;Among other things&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From C I learned that with great power comes great responsibility.&lt;/p&gt;

&lt;p&gt;So, here are my 2 cents: Learn at least one programming language that's not your main one and use it. Expand you horizons, learn something new, learn Go. It will make you a better programmer.&lt;/p&gt;

&lt;p&gt;Go is not the first language to implement some of its features but is the first to have them implemented well. Companies (and people) are using Go in production, in software that is changing the world. Some features present in Go that I didn't see in any other language until now are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concurrent primitives instead of threads or callbacks&lt;/li&gt;
&lt;li&gt;Error values instead of exceptions and try/catch&lt;/li&gt;
&lt;li&gt;Object orientation without classes nor inheritance&lt;/li&gt;
&lt;li&gt;First class testing support&lt;/li&gt;
&lt;li&gt;Deferred execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go also shares features with other programming languages, but implemented in different ways. Those ways let you see the world from a different perspective. A better perspective.&lt;/p&gt;

&lt;p&gt;Those features are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Interfaces: my favourite feature of Go.&lt;/li&gt;
&lt;li&gt;It's &lt;a href="https://github.com/golang/go" rel="noopener noreferrer"&gt;open source&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://golang.org/doc/go1compat" rel="noopener noreferrer"&gt;The Go 1 compatibility promise&lt;/a&gt;: Go 1 programs will always compile.&lt;/li&gt;
&lt;li&gt;Type inference: in a statically typed language this is pure gold.&lt;/li&gt;
&lt;li&gt;Compiled to machine code: it doesn't run in an interpreter or virtual machine, it runs fast and use less resources than others.&lt;/li&gt;
&lt;li&gt;Fast compile times: you can compile several thousand of files into a single executable file in less than a second.&lt;/li&gt;
&lt;li&gt;Garbage collected: you don't have to manage memory by hand.&lt;/li&gt;
&lt;li&gt;Ease of use: tools such as "go build", "go test" and "go get" simplify the development cycle&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you learn Go you will acquire a different mindset. You will learn something new. You will see the world from a different perspective and that in itself can be a great thing for you and your career. No matter what language you use in 5 or 10 years from now.&lt;/p&gt;

</description>
      <category>go</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
