<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es"><title>Chemaclass - testing</title><subtitle>Tech Lead compartiendo ideas prácticas sobre artesanía del software, TDD, liderazgo, Bitcoin e IA. Artículos, resúmenes de libros y charlas.</subtitle><link rel="self" type="application/atom+xml" href="https://chemaclass.com/es/tags/testing/atom.xml"/><link rel="alternate" type="text/html" href="https://chemaclass.com"/><generator uri="https://www.getzola.org/">Zola</generator><updated>2024-10-30T00:00:00+00:00</updated><id>https://chemaclass.com/es/tags/testing/atom.xml</id><entry xml:lang="es"><title>bashunit</title><subtitle>Convirtiendo frustraciones en herramientas para mejor desarrollo</subtitle><category term="bashunit" scheme="https://chemaclass.com/tags/bashunit/" label="Bashunit"/><category term="bash" scheme="https://chemaclass.com/tags/bash/" label="Bash"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="open-source" scheme="https://chemaclass.com/tags/open-source/" label="Open Source"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><published>2024-10-30T00:00:00+00:00</published><updated>2024-10-30T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/bashunit/"/><id>https://chemaclass.com/es/blog/bashunit/</id><summary type="html">bashunit es un framework de testing ligero y fácil de usar para Bash, repleto de características útiles como testing paralelo y de snapshots, dobles de test, data providers y toneladas de assertions incorporadas. Respaldado por documentación clara y una comunidad activa, se ha convertido en un favorito para testing confiable en Bash. Lo que comenzó como una simple frustración de desarrollo ha crecido hasta convertirse en una herramienta open-source que hace que el testing en Bash sea mucho más fácil y divertido.</summary><content type="html">&lt;p>bashunit es un framework de testing ligero y fácil de usar para Bash. Características como testing paralelo y de snapshots, dobles de test, data providers y toneladas de assertions incorporadas.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>Respaldado por documentación clara y una comunidad activa, se ha convertido en un favorito para testing confiable en Bash. Lo que comenzó como una simple frustración de desarrollo ha crecido hasta convertirse en una herramienta open-source que hace que el testing en Bash sea mucho más fácil y divertido.&lt;/p>
&lt;ol>
&lt;li>La historia detrás de bashunit&lt;/li>
&lt;li>¿Por qué crear otra librería de testing?&lt;/li>
&lt;li>¿Cómo está hoy en día?&lt;/li>
&lt;li>Características principales&lt;/li>
&lt;li>Lightning tech talk&lt;/li>
&lt;/ol>
&lt;h2 id="la-historia-detras-de-bashunit">La historia detrás de bashunit
&lt;a class="heading-anchor" href="#la-historia-detras-de-bashunit" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El viaje para crear bashunit comenzó con una simple frustración: trabajaba con un equipo donde cada commit tenía que empezar con el nombre del ticket. Como me gusta trabajar en pequeños pasos con commits rápidos e iterativos, añadir la clave y número del ticket a cada commit se convirtió en un gran obstáculo, ralentizando mi flujo de desarrollo con fricción innecesaria.&lt;/p>
&lt;p>Después de unos días así, decidí automatizarlo. Git tiene un hook útil, &lt;code>prepare-commit-msg&lt;/code>, que te permite alterar los mensajes de commit antes de que se finalicen. Creé un (&lt;a rel="external" href="https://github.com/Chemaclass/conventional-commits/blob/main/git-hooks/prepare-commit-msg.sh">script&lt;/a>) en Bash que automáticamente obtiene la clave y número del ticket del nombre de la rama y lo inserta en el mensaje del commit, haciendo mi proceso más fluido y eficiente.&lt;/p>
&lt;p>Como alguien que valora la mejora continua, comencé a añadir más características a este script. Sin embargo, se hizo evidente que mantener y probar estos cambios manualmente llevaba demasiado tiempo y era propenso a errores. Para hacer el desarrollo más seguro y eficiente, creé una función &lt;code>assert&lt;/code>(&lt;a rel="external" href="https://github.com/Chemaclass/conventional-commits/blob/705489a3487a4607183090d5574827bf6fedabda/git-hooks/prepare-commit-msg_test.sh">enlace&lt;/a>), permitiendo tests automatizados que verificaban el comportamiento esperado basado en la salida del script.&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-10-30/bashunit-original-assert.jpg" alt="bashunit-original-assert.jpg" />&lt;/p>
&lt;p>La función &lt;code>assert&lt;/code> me permitió definir múltiples assertions en un archivo separado, facilitando la validación de que cualquier refactorización del hook original mantuviera el comportamiento esperado. Si un cambio rompía inadvertidamente la funcionalidad existente, lo señalaría instantáneamente, haciéndome saber de inmediato que algo necesitaba arreglarse. Esta configuración proporcionaba retroalimentación inmediata y ayudaba a asegurar que cualquier actualización al script no interrumpiera su lógica prevista. Por ejemplo:&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-10-30/conventional-commits-original-tests.jpg" alt="conventional-commits-original-tests.jpg" />&lt;/p>
&lt;p>En el ejemplo anterior, notarás que ejecuto el “&lt;code>SCRIPT&lt;/code>” real como el segundo argumento en la función assert, comparando su salida con el valor esperado proporcionado como primer argumento. Aquí, tenemos dos casos de test, cada uno exportando &lt;code>TEST_BRANCH&lt;/code> para simular cómo el mensaje del commit variaría según el nombre de la rama. Esta configuración emula el comportamiento real, permitiéndonos probar cómo diferentes nombres de rama afectan el formato del mensaje del commit. Más ejemplos &lt;a rel="external" href="https://github.com/Chemaclass/conventional-commits/blob/27aeebe4e76afe0a2e91cba85537399eab112eb4/test/prepare-commit-msg_test.sh">aquí&lt;/a>.&lt;/p>
&lt;p>Decidí separar la función &lt;code>assert&lt;/code> de los casos de test, como se muestra &lt;a rel="external" href="https://github.com/Chemaclass/conventional-commits/commit/5458e5728296bb94b1e8e6b25eeccde6cc700589">aquí&lt;/a>, para mantener las cosas modulares y reutilizables. Luego, creé un &lt;code>runner&lt;/code> para ejecutar cada caso de test independientemente, reduciendo la interferencia entre tests y mejorando la confiabilidad. Puedes ver esa configuración &lt;a rel="external" href="https://github.com/Chemaclass/conventional-commits/commit/92a5880d7f26b3422de6b91b51c04f9ff7b961fd">aquí&lt;/a>. Esta estructura hizo el testing automatizado más fácil y la refactorización más segura.&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-10-30/conventional-commits-call_test_functions.jpg" alt="conventional-commits-call_test_functions.jpg" />&lt;/p>
&lt;p>Esta fue una gran mejora porque facilitó separar los &lt;a rel="external" href="https://github.com/Chemaclass/conventional-commits/blob/4c7dae8d44d425ff06fbb48654388f90c2beb3c4/tests/prepare-commit-msg_test.sh">casos de test&lt;/a> de la lógica del runner de tests en sí. Esta estructura clara ha simplificado tanto la creación como la gestión de tests.&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-10-30/conventional-commits-refactor-test-cases.webp" alt="conventional-commits-refactor-test-cases.jpg" />&lt;/p>
&lt;p>Ahora los tests estaban organizados y tuve una &lt;a rel="external" href="https://github.com/Chemaclass/conventional-commits/commit/f459f43cecc271becb1e5eb6ca95d24c97e87830">idea&lt;/a>:&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-10-30/bashunit-idea.jpg" alt="nota de la idea de bashunit" />&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="markdown">&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);font-weight: bold;">##&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);font-weight: bold;"> Idea de seguimiento&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>Separar la lógica de testing en otro repositorio,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>para que pueda ser reutilizada en cualquier lugar.&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Y así &lt;a rel="external" href="https://github.com/TypedDevs/bashunit/commit/27269c21c8d0b03bcb3f2000767f4a27b8bf08a1">comenzó&lt;/a>. En ese momento, no sabía mucho sobre Bash o las mejores formas de usar un proyecto Bash como dependencia. Pero sabía que podía empezar usando un submódulo de Git, aunque no soy muy fan de ellos.&lt;/p>
&lt;p>El 4 de septiembre de 2023, lancé la versión &lt;a rel="external" href="https://github.com/TypedDevs/bashunit/commit/fc9aac40eb8e5ad4483f08d79eb678a3650dcf78">0.1&lt;/a>, que presentaba un runner funcional y una única función de assertion: &lt;code>assertEquals&lt;/code>. Más tarde, se lanzó la versión &lt;a rel="external" href="https://github.com/TypedDevs/bashunit/commit/b546c693198870dd75d1a102b94f4ddad6f4f3ea#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4edR12">0.2&lt;/a>, permitiendo que &lt;code>./bashunit&lt;/code> fuera un ejecutable independiente, ejecutable desde cualquier carpeta. Así es como se veía entonces:&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-10-30/bashunit-02-demo.jpg" alt="bashunit-02-demo.jpg" />&lt;/p>
&lt;p>Compartí el proyecto con algunos amigos que rápidamente se unieron para ayudar con la documentación, el sitio web, assertions adicionales, testing de snapshots y decisiones clave. Para enfatizar su espíritu open-source y propiedad comunitaria, lo moví a una organización que creamos específicamente para compartir proyectos OSS, convirtiéndolo en un proyecto verdaderamente colaborativo en lugar de uno individual.&lt;/p>
&lt;h2 id="por-que-crear-otra-libreria-de-testing">¿Por qué crear otra librería de testing?
&lt;a class="heading-anchor" href="#por-que-crear-otra-libreria-de-testing" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Ahora sé que existen otras librerías de testing para Bash. Pero cuando empecé con bashunit, no las conocía, y francamente, todavía no soy un experto en Bash. Para cuando me enteré de estas alternativas, ya era demasiado tarde, bashunit había ganado suficiente impulso y entusiasmo para seguir adelante.&lt;/p>
&lt;p>Mientras que esas otras librerías pueden servir casos de uso específicos, usar Bash moderno, o ser desarrolladas por desarrolladores de Bash más experimentados, bashunit aspira a diferenciarse ofreciendo una gran experiencia de desarrollador, moldeada por años de trabajo con varios frameworks de testing.&lt;/p>
&lt;p>Me preguntaron sobre las diferencias el 7 de septiembre de 2023, y aquí está mi respuesta:
&lt;a rel="external" href="https://github.com/TypedDevs/bashunit/issues/8">Pregunta: Diferencia con pgrange/bash_unit&lt;/a>.&lt;/p>
&lt;h2 id="como-esta-hoy-en-dia">¿Cómo está hoy en día?
&lt;a class="heading-anchor" href="#como-esta-hoy-en-dia" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Hoy, puedes &lt;a rel="external" href="https://bashunit.typeddevs.com/installation">instalar&lt;/a> bashunit via curl, Homebrew, MacPorts, descargando el último &lt;a rel="external" href="https://github.com/TypedDevs/bashunit/releases">release de GitHub&lt;/a>, o incluso &lt;a rel="external" href="https://github.com/TypedDevs/bashunit/blob/main/build.sh">compilándolo tú mismo&lt;/a> desde el código fuente. Completamente open-source.&lt;/p>
&lt;p>El proyecto está escrito en Bash 3.2 (de 2007) ya que esa es la versión por defecto en macOS, incluso ahora, en 2024. Esta compatibilidad significa que bashunit funciona sin problemas en esa versión, y planeo mantener el soporte para ella.&lt;/p>
&lt;p>Para asegurar la calidad, probamos cada característica con tests unitarios, funcionales y de aceptación, haciendo que bashunit sea su propio “primer usuario” de cada nueva característica. También tenemos varios workflows de CI usando &lt;a rel="external" href="https://github.com/TypedDevs/bashunit/actions/workflows/tests.yml">GitHub actions&lt;/a> que ejecutan tests en diferentes plataformas para verificar compatibilidad y confirmar que todo funciona como se promete.&lt;/p>
&lt;p>&lt;img src="/images/blog/2024-10-30/bashunit-ci.jpg" alt="bashunit-ci.jpg" />&lt;/p>
&lt;p>En junio de 2024, bashunit fue &lt;a rel="external" href="https://bashunit.typeddevs.com/blog/2024-06-21-phpstan-integration">integrado en PHPStan&lt;/a> para sus tests end-to-end, permitiendo el uso de las assertions de bashunit independientemente de su runner. Esta flexibilidad resultó ser muy útil.&lt;/p>
&lt;p>El verano pasado, fui invitado a hablar sobre bashunit en la &lt;a href="/es/talks/#may">International PHP Conference&lt;/a> en Berlín, junto con &lt;a rel="external" href="https://emmanuelvalverde.dev/">Manu&lt;/a>, otro contribuidor. Este proyecto ha abierto puertas y ha llevado a mucha gratitud de usuarios que aprecian el trabajo que hemos puesto en él.&lt;/p>
&lt;h2 id="caracteristicas-principales">Características principales
&lt;a class="heading-anchor" href="#caracteristicas-principales" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>bashunit incluye funciones clásicas del ciclo de vida como &lt;code>set_up&lt;/code>, &lt;code>tear_down&lt;/code>, &lt;code>set_up_before_script&lt;/code> y &lt;code>tear_down_after_script&lt;/code>.&lt;/p>
&lt;p>También soporta una amplia gama de &lt;a rel="external" href="https://bashunit.typeddevs.com/command-line">parámetros de línea de comandos&lt;/a>
y &lt;a rel="external" href="https://bashunit.typeddevs.com/configuration">valores de configuración&lt;/a>. Algunos de mis favoritos incluyen:&lt;/p>
&lt;ul>
&lt;li>&lt;code>--parallel&lt;/code>&lt;/li>
&lt;li>&lt;code>--filter&lt;/code>&lt;/li>
&lt;li>&lt;code>--stop-on-failure&lt;/code>&lt;/li>
&lt;li>&lt;code>--verbose&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>También proporcionamos &lt;a rel="external" href="https://bashunit.typeddevs.com/data-providers">data providers&lt;/a> para ejecutar los mismos casos de test con diferentes inputs.&lt;/p>
&lt;p>Para &lt;a rel="external" href="https://bashunit.typeddevs.com/test-doubles">dobles de test&lt;/a>, bashunit ofrece mocks y spies. Estos funcionan dentro del mismo proceso que el test, pero actualmente no funcionan entre procesos, un área para mejorar.&lt;/p>
&lt;p>Incluye potente &lt;a rel="external" href="https://bashunit.typeddevs.com/snapshots">testing de snapshots&lt;/a>, facilitando la verificación de salidas de comandos o scripts a lo largo del tiempo.&lt;/p>
&lt;p>bashunit ofrece un amplio conjunto de &lt;a rel="external" href="https://bashunit.typeddevs.com/assertions">assertions&lt;/a> nativas para casos de test, incluyendo:&lt;/p>
&lt;ul>
&lt;li>&lt;code>assert_same&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_equals&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_contains&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_matches&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_string_starts_with&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_array_contains&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_successful_code&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_general_error&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_file_exists&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_file_contains&lt;/code>&lt;/li>
&lt;li>&lt;code>assert_match_snapshot&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Incluso puedes crear tus propias &lt;a rel="external" href="https://bashunit.typeddevs.com/custom-asserts">assertions personalizadas&lt;/a> para extender las capacidades de bashunit.&lt;/p>
&lt;p>Con más de &lt;strong>25&lt;/strong> contribuidores y más de &lt;strong>325&lt;/strong> estrellas en GitHub en solo un año de desarrollo en tiempo libre, estoy genuinamente orgulloso de lo que este proyecto se ha convertido.&lt;/p>
&lt;h2 id="lightning-tech-talk">Lightning tech talk
&lt;a class="heading-anchor" href="#lightning-tech-talk" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Recientemente, presenté una lightning tech talk en un meetup de hackers, haciendo una demo de bashunit a una audiencia de más de 100 personas. ¡Fue una experiencia increíble compartir esta herramienta con una audiencia tan comprometida!&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/SX7iNHaSsF0"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;hr />
&lt;p>Logo original de bashunit diseñado por &lt;a rel="external" href="https://antonio.gg/">Antonio&lt;/a>.&lt;/p></content></entry><entry xml:lang="es"><title>¿Cómo Testear Métodos Privados?</title><subtitle>Testeando métodos privados. ¿Cuándo y cómo?</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2023-10-20T00:00:00+00:00</published><updated>2023-10-20T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/how-to-test-private-methods/"/><id>https://chemaclass.com/es/blog/how-to-test-private-methods/</id><summary type="html">De vez en cuando he tenido que enfrentar esta pregunta: ¿cómo testear métodos privados? He recopilado en un artículo las técnicas que suelo usar.</summary><content type="html">&lt;p>Esta pregunta me la han hecho muchas veces a lo largo de los años. Aquí recopilo mis ideas al respecto.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="respuesta-corta">Respuesta corta
&lt;a class="heading-anchor" href="#respuesta-corta" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Nunca.&lt;/p>
&lt;h2 id="respuesta-larga">Respuesta larga
&lt;a class="heading-anchor" href="#respuesta-larga" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Nunca jamás.&lt;/p>
&lt;hr />
&lt;h2 id="y-si">¿Y si…?
&lt;a class="heading-anchor" href="#y-si" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Si realmente quieres testear un método privado, considera extraer esa lógica del método privado en una clase separada, y escribe un test unitario para el comportamiento de esa clase.&lt;/p>
&lt;blockquote>
&lt;p>Para este, me inspiré en el &lt;a rel="external" href="https://franiglesias.github.io/test-private-methods/">post original&lt;/a> de Fran Iglesias.&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>¿Equipos de QA Dedicados en Software?</title><subtitle>¿Cómo encaja una persona QA dedicada en tu equipo agile?</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><published>2023-05-17T00:00:00+00:00</published><updated>2023-05-17T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/dedicated-qa-teams/"/><id>https://chemaclass.com/es/blog/dedicated-qa-teams/</id><summary type="html">Esto será controvertido, pero hablemos de la posición de QA. La verdad oculta detrás de la falta de calidad del software y por qué esto debería preocuparte si escribes software.</summary><content type="html">&lt;p>Esto será controvertido, pero hablemos de la posición de QA. La verdad oculta detrás de la falta de calidad del software y por qué esto debería preocuparte si escribes software.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="qa-es-un-rol-no-una-posicion">QA es un rol, no una posición
&lt;a class="heading-anchor" href="#qa-es-un-rol-no-una-posicion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Como desarrollador de software, cuando escribes software, eres responsable de la calidad de lo que sea que estés escribiendo. Una tercera persona actuando como QA podría encontrar que tu solución no funciona como se esperaba, pero ¿cómo es posible? Podrías argumentar que podrían encontrar casos límite, pero ¿cómo podría ser posible si el software ya fue testeado previamente?&lt;/p>
&lt;p>El objetivo final de un equipo de software es hacer la posición de QA inútil porque no deberían encontrar nada más que software bien funcionando. Pero ¿cómo llegas a ese punto? ¿Cómo podemos asegurar que el software que escribimos funciona como se espera y no hay necesidad de una persona QA en nuestro equipo?&lt;/p>
&lt;h2 id="la-verdad-oculta-detras-de-la-falta-de-calidad-del-software">La verdad oculta detrás de la falta de calidad del software
&lt;a class="heading-anchor" href="#la-verdad-oculta-detras-de-la-falta-de-calidad-del-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Desafortunadamente, en nuestra industria del software, la demanda de proyectos “rápidos, rápidos y sucios” terminó en MVPs pobremente desarrollados simplemente aplicando parches y código sobre código con solo testing manual comprobando caminos felices, a veces incluso ignorando casos límite.&lt;/p>
&lt;blockquote>
&lt;p>“La fecha límite es en una semana, ¡así que mejor termínalo a tiempo!”&lt;/p>
&lt;/blockquote>
&lt;p>No aprendemos la importancia de lo que el testing automatizado puede aportar a nuestro trabajo diario, así que no lo tomamos en serio, y por lo tanto, no lo practicamos lo suficiente. Y, por esa misma razón, porque no lo practicamos, no sabemos cómo realizarlo correctamente. ¡Sí, estoy hablando de escribir tests automatizados que prueban el comportamiento de tu software!&lt;/p>
&lt;p>Nuestra incapacidad para escribir código testeable resulta en software que es difícil de testear, y por lo tanto delegamos el testing a terceros trasladando la responsabilidad de la calidad final general del producto o servicio que escribimos.&lt;/p>
&lt;h2 id="la-practica-hace-al-maestro">La práctica hace al maestro
&lt;a class="heading-anchor" href="#la-practica-hace-al-maestro" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Debes aprender y aplicar técnicas de testing apropiadas cuando tengan sentido. ¿Cómo y cuándo usar efectivamente dobles de test, preparar tests solitarios o sociables, qué compromisos y razones respaldan tu mente al elegir uno u otro camino hacia tus estrategias de testing?&lt;/p>
&lt;p>Eres la última y principal persona responsable de tu conocimiento, así que mejor invierte en ti mismo porque nadie más lo hará por ti.&lt;/p>
&lt;p>Mira todo lo que haces como una oportunidad de aprendizaje. Practica y mejora por defecto en todo lo que haces.&lt;/p>
&lt;p>Si no sabes cómo empezar, aquí está mi consejo favorito: siempre puedes practicar y mejorar tus habilidades de testing usando katas de código. Lee más sobre este tema &lt;a href="/es/blog/test-driven-development/">aquí&lt;/a>.&lt;/p>
&lt;h2 id="buena-teoria-pero-para-que-molestarse">Buena teoría, pero… ¿para qué molestarse?
&lt;a class="heading-anchor" href="#buena-teoria-pero-para-que-molestarse" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El testing manual es, por supuesto, necesario. Es otra estrategia de testing que no estoy culpando o atacando. Aún podríamos necesitar una persona dedicada a cargo de descubrir qué nuevas funcionalidades queremos construir para satisfacer a nuestros clientes. Pero este post no es sobre esa posición.&lt;/p>
&lt;p>Se trata de acortar el bucle de retroalimentación. Si puedes escribir software para que funcione de maneras específicas, ¿no puedes escribir tests automatizados para probar que el software que escribiste se comporta de la manera que esperas?&lt;/p>
&lt;p>Si has cubierto con tests automatizados el comportamiento de tu software a cualquier nivel que tenga sentido, ¿qué queda para una persona QA dedicada?&lt;/p>
&lt;p>La próxima vez que pienses “Necesitamos una persona QA para testear esto”, intenta el ejercicio de pensar en cambio, “¿Cómo puedo escribir un test automatizado que verifique lo que esperaría si una persona QA estuviera comprobando esto?”&lt;/p>
&lt;p>Y así es como cambias la “posición de QA a tiempo completo” en una “mentalidad de rol para todos los que escriben software.”&lt;/p>
&lt;p>El código nunca miente y nunca olvida; una vez que está escrito y automatizado en tu pipeline, puedes ejecutarlo en cualquier momento sin coste.&lt;/p>
&lt;p>&lt;img src="/images/blog/2023-05-17/footer.webp" alt="blog-footer" />&lt;/p></content></entry><entry xml:lang="es"><title>Artesanía Limpia</title><subtitle>Disciplinas, Estándares y Ética</subtitle><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="xp" scheme="https://chemaclass.com/tags/xp/" label="Xp"/><published>2022-07-11T00:00:00+00:00</published><updated>2022-07-11T00:00:00+00:00</updated><author><name>
Robert C. Martin</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/clean-craftsmanship/"/><id>https://chemaclass.com/es/readings/clean-craftsmanship/</id><summary type="html">Disciplinas, estándares y ética del desarrollo de software profesional.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>El libro tiene tres partes: disciplinas, estándares y ética.&lt;/p>
&lt;p>La primera es la más técnica. Te guía con ejemplos de TDD y muestra cómo el testing te ayuda a diseñar tu código.&lt;/p>
&lt;p>La segunda trata sobre productividad, calidad y coraje.&lt;/p>
&lt;p>La tercera explica cómo hemos llegado hasta aquí como profesionales del software y nuestra responsabilidad ética: no hacer daño, integridad y trabajo en equipo.&lt;/p>
&lt;hr />
&lt;p>Una de mis partes favoritas del libro:&lt;/p>
&lt;blockquote>
&lt;p>Nuestra industria es dinámica y cambia constantemente. Hay que aprender de forma continua y agresiva.&lt;/p>
&lt;p>¿Cómo y cuándo aprendes? Si tu empresa te da tiempo para ello, aprovéchalo al máximo. Si no, tendrás que hacerlo por tu cuenta.&lt;/p>
&lt;p>Prepárate para dedicar varias horas al mes. Reserva ese tiempo.&lt;/p>
&lt;p>Sí, ya sé: familia, facturas, viajes, la vida. Pero también tienes una profesión. Y las profesiones requieren cuidado y mantenimiento. Aprendamos de forma continua y agresiva.&lt;/p>
&lt;p>&lt;code>Capítulo 11. Coraje - Aprendizaje Agresivo Continuo&lt;/code>&lt;/p>
&lt;/blockquote>
&lt;hr />
&lt;h2 id="indice">Índice
&lt;a class="heading-anchor" href="#indice" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="parte-i-las-disciplinas">Parte I: Las Disciplinas
&lt;a class="heading-anchor" href="#parte-i-las-disciplinas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="capitulo-1-artesania">Capítulo 1. Artesanía
&lt;a class="heading-anchor" href="#capitulo-1-artesania" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Extreme Programming&lt;/li>
&lt;li>Test-Driven Development&lt;/li>
&lt;li>Refactoring&lt;/li>
&lt;li>Diseño Simple&lt;/li>
&lt;li>Programación Colaborativa&lt;/li>
&lt;li>Tests de Aceptación&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-2-test-driven-development">Capítulo 2. Test-Driven Development
&lt;a class="heading-anchor" href="#capitulo-2-test-driven-development" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Visión General&lt;/li>
&lt;li>Lo Básico&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-3-tdd-avanzado">Capítulo 3. TDD Avanzado
&lt;a class="heading-anchor" href="#capitulo-3-tdd-avanzado" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Quedarse Atascado&lt;/li>
&lt;li>Arrange, Act, Assert&lt;/li>
&lt;li>Test Doubles&lt;/li>
&lt;li>Arquitectura&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-4-diseno-de-tests">Capítulo 4. Diseño de Tests
&lt;a class="heading-anchor" href="#capitulo-4-diseno-de-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Testeando Bases de Datos&lt;/li>
&lt;li>Testeando GUIs&lt;/li>
&lt;li>Patrones de Test&lt;/li>
&lt;li>Subclase Específica de Test&lt;/li>
&lt;li>Humble Object&lt;/li>
&lt;li>Diseño de Tests&lt;/li>
&lt;li>Rompiendo la Correspondencia&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-5-refactoring">Capítulo 5. Refactoring
&lt;a class="heading-anchor" href="#capitulo-5-refactoring" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>¿Qué es Refactoring?&lt;/li>
&lt;li>El Kit Básico de Herramientas&lt;/li>
&lt;li>Extract Method&lt;/li>
&lt;li>Las Disciplinas&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-6-diseno-simple">Capítulo 6. Diseño Simple
&lt;a class="heading-anchor" href="#capitulo-6-diseno-simple" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>YAGNI&lt;/li>
&lt;li>Cubierto por Tests&lt;/li>
&lt;li>Cobertura&lt;/li>
&lt;li>¿Diseño?&lt;/li>
&lt;li>Maximizar Expresión&lt;/li>
&lt;li>La Abstracción Subyacente&lt;/li>
&lt;li>Minimizar Duplicación&lt;/li>
&lt;li>Minimizar Tamaño&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-7-programacion-colaborativa">Capítulo 7. Programación Colaborativa
&lt;a class="heading-anchor" href="#capitulo-7-programacion-colaborativa" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;h4 id="capitulo-8-tests-de-aceptacion">Capítulo 8. Tests de Aceptación
&lt;a class="heading-anchor" href="#capitulo-8-tests-de-aceptacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>La Disciplina&lt;/li>
&lt;li>El Build Continuo&lt;/li>
&lt;/ul>
&lt;h3 id="parte-ii-los-estandares">Parte II: Los Estándares
&lt;a class="heading-anchor" href="#parte-ii-los-estandares" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="capitulo-9-productividad">Capítulo 9. Productividad
&lt;a class="heading-anchor" href="#capitulo-9-productividad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Nunca Enviaremos M***da&lt;/li>
&lt;li>Adaptabilidad Económica&lt;/li>
&lt;li>Siempre Estaremos Listos&lt;/li>
&lt;li>Productividad Estable&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-10-calidad">Capítulo 10. Calidad
&lt;a class="heading-anchor" href="#capitulo-10-calidad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Mejora Continua&lt;/li>
&lt;li>Competencia Sin Miedo&lt;/li>
&lt;li>Calidad Extrema&lt;/li>
&lt;li>No Volcaremos en QA&lt;/li>
&lt;li>QA No Encontrará Nada&lt;/li>
&lt;li>Automatización de Tests&lt;/li>
&lt;li>Testing Automatizado e Interfaces de Usuario&lt;/li>
&lt;li>Testeando la Interfaz de Usuario&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-11-coraje">Capítulo 11. Coraje
&lt;a class="heading-anchor" href="#capitulo-11-coraje" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Nos Cubrimos Mutuamente&lt;/li>
&lt;li>Estimaciones Honestas&lt;/li>
&lt;li>Debes Decir NO&lt;/li>
&lt;li>Aprendizaje Agresivo Continuo&lt;/li>
&lt;li>Mentoría&lt;/li>
&lt;/ul>
&lt;h3 id="parte-iii-la-etica">Parte III: La Ética
&lt;a class="heading-anchor" href="#parte-iii-la-etica" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>El Primer Programador&lt;/li>
&lt;li>Setenta y Cinco Años&lt;/li>
&lt;li>Nerds y Salvadores&lt;/li>
&lt;li>Modelos a Seguir y Villanos&lt;/li>
&lt;li>Gobernamos el Mundo&lt;/li>
&lt;li>Catástrofes&lt;/li>
&lt;li>El Juramento&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-12-dano">Capítulo 12. Daño
&lt;a class="heading-anchor" href="#capitulo-12-dano" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Primero, No Hacer Daño&lt;/li>
&lt;li>Mejor Trabajo&lt;/li>
&lt;li>Prueba Repetible&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-13-integridad">Capítulo 13. Integridad
&lt;a class="heading-anchor" href="#capitulo-13-integridad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Ciclos Pequeños&lt;/li>
&lt;li>Mejora Implacable&lt;/li>
&lt;li>Mantener Alta Productividad&lt;/li>
&lt;/ul>
&lt;h4 id="capitulo-14-trabajo-en-equipo">Capítulo 14. Trabajo en Equipo
&lt;a class="heading-anchor" href="#capitulo-14-trabajo-en-equipo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>Trabajar como Equipo&lt;/li>
&lt;li>Estimar Honesta y Justamente&lt;/li>
&lt;li>Respeto&lt;/li>
&lt;li>Nunca Dejes de Aprender&lt;/li>
&lt;/ul>
&lt;hr />
&lt;p>Charla de Uncle Bob donde cubre la mayoría de los temas del libro.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/sPXk11hrWTM"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="plain">&lt;span class="giallo-l">&lt;span>Escucha sobre:&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Cita e Intro - [00:00:00]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Trayectoria Profesional - [00:07:29]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Clean Craftsmanship - [00:10:53]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Programador como Profesión - [00:15:31]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Artesanía - [00:18:45]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Disciplinas - [00:22:45]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Disciplinas: Test-Driven Development - [00:28:49]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Disciplinas: Refactoring - [00:34:31]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Cobertura de Código - [00:39:02]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Estándar: Nunca Enviar M***da - [00:42:35]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Estándar: Siempre Estar Listo - [00:47:15]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Ética: No Hacer Daño - [00:50:00]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* Ética: Estimar Honestamente - [00:53:56]&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>* 2 Sabiduría de Tech Lead - [00:57:50]&lt;/span>&lt;/span>&lt;/code>&lt;/pre></content></entry><entry xml:lang="es"><title>Ingeniería de Software Moderna</title><subtitle>Haciendo lo que funciona para construir mejor software más rápido</subtitle><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="architecture" scheme="https://chemaclass.com/tags/architecture/" label="Architecture"/><category term="agile" scheme="https://chemaclass.com/tags/agile/" label="Agile"/><published>2022-06-29T00:00:00+00:00</published><updated>2022-06-29T00:00:00+00:00</updated><author><name>
David Farley</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/modern-software-engineering/"/><id>https://chemaclass.com/es/readings/modern-software-engineering/</id><summary type="html">El desarrollo de software como práctica de ingeniería real. Para dominarlo hay que ser experto en aprender y gestionar la complejidad.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>
&lt;p>El libro presenta el desarrollo de software como una práctica de ingeniería real. Para dominarlo hay que ser experto en aprender y gestionar la complejidad.&lt;/p>
&lt;h3 id="optimizar-para-aprender">Optimizar para aprender
&lt;a class="heading-anchor" href="#optimizar-para-aprender" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El libro presenta cinco comportamientos clave para aprender mejor:&lt;/p>
&lt;ul>
&lt;li>Trabajar de forma iterativa&lt;/li>
&lt;li>Buscar feedback&lt;/li>
&lt;li>Incrementalismo&lt;/li>
&lt;li>Empirismo&lt;/li>
&lt;li>Ser experimental&lt;/li>
&lt;/ul>
&lt;p>La idea central: trabajar en pasos pequeños, recoger feedback y ajustar.&lt;/p>
&lt;h3 id="optimizar-para-gestionar-la-complejidad">Optimizar para gestionar la complejidad
&lt;a class="heading-anchor" href="#optimizar-para-gestionar-la-complejidad" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Cinco ideas para manejar la complejidad:&lt;/p>
&lt;ul>
&lt;li>Modularidad&lt;/li>
&lt;li>Cohesión&lt;/li>
&lt;li>Separación de responsabilidades&lt;/li>
&lt;li>Ocultación de información y abstracción&lt;/li>
&lt;li>Gestión del acoplamiento&lt;/li>
&lt;/ul>
&lt;p>Gestionar la complejidad de nuestros sistemas es fundamental.&lt;/p>
&lt;h3 id="herramientas-para-apoyar-la-ingenieria">Herramientas para apoyar la ingeniería
&lt;a class="heading-anchor" href="#herramientas-para-apoyar-la-ingenieria" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El libro profundiza en ideas como:&lt;/p>
&lt;ul>
&lt;li>Testeabilidad&lt;/li>
&lt;li>Desplegabilidad&lt;/li>
&lt;li>Control de variables&lt;/li>
&lt;li>Entrega continua&lt;/li>
&lt;/ul>
&lt;hr />
&lt;p>Un vídeo donde el autor explica las ideas principales del libro:&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/TRqYQnCfgH8"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>London vs Chicago</title><subtitle>Es una integración, no una elección</subtitle><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2021-11-20T00:00:00+00:00</published><updated>2021-11-20T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/london-vs-chicago/"/><id>https://chemaclass.com/es/blog/london-vs-chicago/</id><summary type="html">Hay dos escuelas conocidas en TDD: la escuela mockista (también conocida como Outside-in) y la escuela clasicista (también conocida como Inside-out).</summary><content type="html">&lt;p>Hay dos escuelas conocidas en TDD: la escuela mockista (también conocida como Outside-in) y la escuela clasicista (también conocida como Inside-out).&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h3 id="por-que-london-y-chicago">¿Por qué London y Chicago?
&lt;a class="heading-anchor" href="#por-que-london-y-chicago" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Dos empresas, una de Londres y otra de Chicago, afirmaban hacer TDD pero con enfoques diferentes. La de Londres construía software de afuera hacia adentro; la de Chicago, de adentro hacia afuera. Veamos cada una.&lt;/p>
&lt;h2 id="outside-in-escuela-de-londres">Outside-in: Escuela de Londres
&lt;a class="heading-anchor" href="#outside-in-escuela-de-londres" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Un enfoque guiado por comportamiento para TDD. Empiezas desde el exterior de la aplicación y vas hacia adentro, bajando a capas inferiores. Por ejemplo, desde la API/Controladores hacia las capas de aplicación o dominio.&lt;/p>
&lt;h3 id="pros">PROS
&lt;a class="heading-anchor" href="#pros" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Enfocado en Comportamiento&lt;/strong>: requiere muchos dobles de test porque testeas abstracciones que aún no existen (creas lógica de alto nivel primero). No escribirás código muerto, pero es fácil crear tests muy acoplados a la lógica, lo que dificulta el refactoring.&lt;/li>
&lt;li>&lt;strong>Separación Comando-Consulta&lt;/strong>: es una disciplina para gestionar efectos secundarios. O realizas una acción (comando) o pides un valor (consulta).&lt;/li>
&lt;/ul>
&lt;h3 id="contras">CONTRAS
&lt;a class="heading-anchor" href="#contras" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Tests Frágiles&lt;/strong>: tiende a crear tests que se rompen fácilmente porque suelen estar muy acoplados al código de producción.&lt;/li>
&lt;li>&lt;strong>Refactoring Difícil&lt;/strong>: por la misma razón, tener tests acoplados hace que el refactoring continuo sea lento y complicado.&lt;/li>
&lt;/ul>
&lt;h2 id="inside-out-escuela-de-chicago">Inside-out: Escuela de Chicago
&lt;a class="heading-anchor" href="#inside-out-escuela-de-chicago" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Un enfoque informal, exploratorio, basado en estado. Empiezas desde el interior de la aplicación (normalmente el dominio) y vas hacia afuera, hacia las APIs.&lt;/p>
&lt;h3 id="pros-1">PROS
&lt;a class="heading-anchor" href="#pros-1" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Red de Seguridad Fuerte&lt;/strong>: produce tests desacoplados de la implementación. Puedes cambiar el software sin miedo a romperlo, ideal para el refactoring continuo.&lt;/li>
&lt;li>&lt;strong>Alta Cohesión&lt;/strong>: a medida que los tests se vuelven más generales, el código de producción se vuelve más específico. Alta cohesión lleva a bajo acoplamiento, lo que mejora extensibilidad, mantenibilidad y testeabilidad.&lt;/li>
&lt;li>&lt;strong>Minimiza Dobles de Test&lt;/strong>: construir de adentro hacia afuera requiere menos dobles porque construyes sobre tests previamente escritos. Esto ayuda a tener tests menos frágiles.&lt;/li>
&lt;/ul>
&lt;h3 id="contras-1">CONTRAS
&lt;a class="heading-anchor" href="#contras-1" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>YAGNI&lt;/strong>: a menudo sobre-diseña soluciones, con código que realmente no se necesita (¡o ni siquiera se usa!) al final.&lt;/li>
&lt;/ul>
&lt;h2 id="londres-y-chicago-funcionan-mejor-juntas">Londres y Chicago funcionan mejor juntas
&lt;a class="heading-anchor" href="#londres-y-chicago-funcionan-mejor-juntas" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>No se trata de elegir uno u otro. Se trata de entender tu contexto y optimizar las cualidades que lo necesitan. London y Chicago tienen sus pros y contras. El mejor enfoque para TDD es integrar ambas escuelas.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/rbSDGr-_UwY"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;hr />
&lt;h3 id="referencias">Referencias
&lt;a class="heading-anchor" href="#referencias" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;a href="/es/blog/test-driven-development/">Test-Driven (Development)&lt;/a>&lt;/li>
&lt;li>&lt;a href="/es/blog/tdd-vs-bdd/">TDD vs BDD&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://gist.github.com/xpepper/2e3519d2cb8568a0b13739d9ae497f21">Notes about “London vs Chicago TDD styles”&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>TDD vs BDD</title><subtitle>¿Diseño o Flujo de trabajo?</subtitle><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2021-09-25T00:00:00+00:00</published><updated>2021-09-25T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/tdd-vs-bdd/"/><id>https://chemaclass.com/es/blog/tdd-vs-bdd/</id><summary type="html">Estas son dos técnicas diferentes. La clave de cada una está en la mentalidad y el contexto de lo que quieres lograr.</summary><content type="html">&lt;p>Estas son dos técnicas diferentes. La clave de cada una está en la mentalidad y el contexto de lo que quieres lograr.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="bdd-es-una-funcionalidad-guiada-por-tests">BDD es una “funcionalidad guiada por tests”
&lt;a class="heading-anchor" href="#bdd-es-una-funcionalidad-guiada-por-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Básicamente, es un desarrollo test-first, donde el enfoque principal es asegurar el comportamiento final esperado, y por lo tanto el resultado de la lógica de software que quieres tener al final.&lt;/p>
&lt;p>En BDD el enfoque principal es el comportamiento de tu lógica de dominio que aún no existe. Es, desde un punto de vista abstracto, sobre toda la funcionalidad y los requisitos del dominio.&lt;/p>
&lt;h2 id="tdd-es-sobre-el-ritmo">TDD es sobre el ritmo
&lt;a class="heading-anchor" href="#tdd-es-sobre-el-ritmo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;ol>
&lt;li>Especifica lo que quieres.&lt;/li>
&lt;li>Hazlo funcionar.&lt;/li>
&lt;li>Hazlo mejor.&lt;/li>
&lt;/ol>
&lt;p>TDD no es solo la ya conocida mentalidad “red-green-refactor”, sino principalmente sobre el flujo de trabajo que te ayuda a entender las constantes decisiones de diseño que haces cada vez para cada lógica que estás diseñando.&lt;/p>
&lt;blockquote>
&lt;p>TDD es sobre retroalimentación constante de tus decisiones.&lt;/p>
&lt;/blockquote>
&lt;p>En el contexto de OOP (para hacer los ejemplos más claros), siempre hay toneladas de formas diferentes de diseñar tu clase:&lt;/p>
&lt;ul>
&lt;li>¿Cuál es el nombre de la clase de este método?&lt;/li>
&lt;li>¿Cuáles son las dependencias o colaboradores de esta clase?&lt;/li>
&lt;li>¿Cómo se comportará esta clase cuando use esta otra clase dentro de ella?&lt;/li>
&lt;li>¿Cuál es el resultado esperado de este método cuando le doy estos argumentos?&lt;/li>
&lt;li>etc, etc…&lt;/li>
&lt;/ul>
&lt;p>Hacemos estas preguntas (y muchas más) cada vez, y también les damos una respuesta, pero normalmente sin ningún pensamiento racional o reflexión sobre ello. Simplemente hacemos lo que creemos que es “lo mejor” en ese momento particular enfocándonos en hacer que algo funcione, pero ¿es suficiente hacerlo funcionar?&lt;/p>
&lt;h2 id="el-bucle-de-retroalimentacion-constante">El bucle de retroalimentación constante
&lt;a class="heading-anchor" href="#el-bucle-de-retroalimentacion-constante" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>El testing no es solo una gran herramienta porque te da una red de seguridad para refactorizar con confianza, sino también porque ayuda a diseñar mejor el sistema. &lt;strong>¿Cómo es eso?&lt;/strong> Porque antes de implementar cualquier solución, te obliga a pensar en las decisiones que necesitas tomar. Te desafías a ti mismo para entender los argumentos de tus decisiones, y por qué A y no B es mejor solución en un contexto particular.&lt;/p>
&lt;p>BDD y TDD no son mutuamente excluyentes, de hecho, pueden y deben coexistir. Depende principalmente del contexto de lo que quieres construir y testear.&lt;/p>
&lt;p>&lt;img src="/images/blog/2021-09-25/bdd-and-tdd.webp" alt="blog-bdd-and-tdd" />&lt;/p>
&lt;p>BDD es sobre desarrollo de funcionalidades Test-First. El objetivo no es el cómo sino el qué. El bucle de retroalimentación es largo porque obtendrás el “verde” una vez que la funcionalidad esté implementada y funcionando como se esperaba.&lt;/p>
&lt;p>TDD también es otro desarrollo guiado por Test-First pero, a diferencia de BDD, se trata de un bucle de retroalimentación más corto y rápido.&lt;/p>
&lt;ol>
&lt;li>Primero, &lt;strong>especificas lo que quieres&lt;/strong>. Piensas sobre el diseño de tu clase o método. Su nombre o firma. Sus dependencias. Pero todo esto con pequeños pasos, uno a la vez.&lt;/li>
&lt;li>Segundo, &lt;strong>haces que esa pequeña cosa funcione&lt;/strong> de la manera más simple posible.&lt;/li>
&lt;li>Finalmente, &lt;strong>lo haces mejor&lt;/strong>. Porque el software es lo suficientemente difícil y complicado como para hacerlo bien al primer intento, así que el refactoring es imprescindible para mantener un sistema saludable. En este punto, con un “test verde ejecutándose”, puedes refactorizar y mejorar tu lógica de forma segura.&lt;/li>
&lt;/ol>
&lt;p>Lo anterior es básicamente TDD, cierto, pero… ¿qué tiene de especial? El &lt;strong>bucle de retroalimentación&lt;/strong> constante y las &lt;strong>decisiones de diseño&lt;/strong> que necesitas tomar antes de escribir realmente la solución. Este es el poder de TDD.&lt;/p>
&lt;h3 id="por-que-pasos-tan-pequenos-en-tdd">¿Por qué pasos tan pequeños en TDD?
&lt;a class="heading-anchor" href="#por-que-pasos-tan-pequenos-en-tdd" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Teóricamente “debes” escribir pequeños pasos para cada iteración, pero ¿por qué? &lt;strong>Se trata del bucle de retroalimentación&lt;/strong>. Esto depende de ti, tus expectativas y tu experiencia con testing.&lt;/p>
&lt;p>&lt;img src="/images/blog/2021-09-25/footer.jpg" alt="pequeños pasos en el bucle de retroalimentación de tdd" />&lt;/p>
&lt;hr />
&lt;h3 id="recursos">Recursos
&lt;a class="heading-anchor" href="#recursos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://chemaclass.com/es/blog/test-driven-development/">https://chemaclass.com/es/blog/test-driven-development/&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://blog.testlodge.com/tdd-vs-bdd/">https://blog.testlodge.com/tdd-vs-bdd/&lt;/a>&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Test-Driven (Development)</title><subtitle>¿Qué tiene de desafiante?</subtitle><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2021-08-01T00:00:00+00:00</published><updated>2021-08-01T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/test-driven-development/"/><id>https://chemaclass.com/es/blog/test-driven-development/</id><summary type="html">TDD es una práctica de diseño, no solo una técnica de testing. Escribir tests primero cambia cómo piensas sobre el código y su estructura.</summary><content type="html">&lt;p>La complejidad aquí no está en escribir tests en sí, sino en los hábitos que tenemos que cambiar para crear software que sea fácil de testear.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="la-raiz-del-problema">La raíz del problema
&lt;a class="heading-anchor" href="#la-raiz-del-problema" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Sin experiencia sólida en testing, los desarrolladores lo pasan mal al intentar aplicar tests en su trabajo diario. No es solo por la complejidad del tema, sino &lt;strong>porque están acostumbrados a escribir código difícil de testear.&lt;/strong>&lt;/p>
&lt;p>Escribir tests para software que ya funciona (sobre todo cuando se hizo sin pensar en testing) se siente aburrido y casi inútil. Viene acompañado de falta de motivación, culpando al sujeto equivocado: “los tests me hacen ir más lento”.&lt;/p>
&lt;blockquote>
&lt;p>En un contexto de dominio, si una pieza de lógica de software es difícil de testear, el problema no es el test, sino el código que no estaba bien escrito.&lt;/p>
&lt;/blockquote>
&lt;p>Ya hay cientos de tutoriales, libros y documentación sobre testing. Aquí comparto mi experiencia y cómo aplico esta filosofía en mi trabajo diario.&lt;/p>
&lt;h3 id="test-driven-se-basa-en-esta-simple-regla">Test-Driven se basa en esta simple regla
&lt;a class="heading-anchor" href="#test-driven-se-basa-en-esta-simple-regla" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>En lugar de: diseñar código -&amp;gt; desarrollar código -&amp;gt; escribir tests.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2021-08-01/non-tdd-style.png" alt="non-tdd-style" />&lt;/p>
&lt;ul>
&lt;li>Se trata de: escribir test automatizado que falla -&amp;gt; ejecutar test que falla -&amp;gt; desarrollar código para hacer pasar el test -&amp;gt; ejecutar test -&amp;gt; repetir.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2021-08-01/tdd-style.png" alt="tdd-style" />&lt;/p>
&lt;p>La idea de guiar tu código con tests depende del nivel de abstracción de lo que estés escribiendo. No quieres acoplar mal los tests con el código testeado. Quieres testear el comportamiento de tu lógica.&lt;/p>
&lt;p>TDD se basa en un bucle de pequeños pasos que te ayuda a encontrar &lt;strong>patrones&lt;/strong> y guiar tu diseño de software con &lt;strong>refactorizaciones constantes&lt;/strong>. Es la mejor opción si quieres asegurar el comportamiento esperado de todos los caminos posibles de tu lógica.&lt;/p>
&lt;p>Lo bonito es que no necesitas conocer el algoritmo completo desde el principio. Vas &lt;strong>descubriendo&lt;/strong> cómo debería ser tu lógica expresando la implementación deseada, paso a paso, en tests automatizados.&lt;/p>
&lt;p>Escribir tests al mismo tiempo que escribes el código te &lt;strong>obliga a escribir mejor software&lt;/strong>. Porque quieres que sea fácil de testear, y eso lleva a mayor calidad.&lt;/p>
&lt;blockquote>
&lt;p>Ya escribí otro post sobre la relación entre &lt;strong>calidad y testing&lt;/strong> del software: &lt;a href="/es/blog/the-art-of-testing/">El Arte del Testing: donde el diseño se encuentra con la calidad&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;h2 id="mejora-tus-habilidades-de-test-driven">Mejora tus habilidades de Test-Driven
&lt;a class="heading-anchor" href="#mejora-tus-habilidades-de-test-driven" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>&lt;img src="/images/blog/2021-08-01/tdd-style-with-git.png" alt="tdd-style" />&lt;/p>
&lt;p>La mejor manera de aprender Test-Driven es haciendo katas de software. Pruébalas solo y con otros. Ambas son igualmente importantes.&lt;/p>
&lt;ul>
&lt;li>Solo: para desafiar tu yo interior sin ninguna distracción excepto tú mismo.&lt;/li>
&lt;li>Con otros: el pair-programming es esencial en nuestro trabajo. Las katas son las mejores herramientas para entrenar nuestras habilidades de comunicación y aprender juntos unos de otros.&lt;/li>
&lt;/ul>
&lt;h3 id="que-es-una-code-kata">¿Qué es una Code Kata?
&lt;a class="heading-anchor" href="#que-es-una-code-kata" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Los desarrolladores no practicamos lo suficiente. La mayor parte de nuestro aprendizaje ocurre en el trabajo, y ahí es donde cometemos la mayoría de nuestros errores.&lt;/p>
&lt;p>Otras profesiones creativas sí practican: los músicos tocan piezas técnicas, los poetas reescriben obras constantemente. En karate, un estudiante dedica la mayor parte del tiempo a aprender y perfeccionar movimientos básicos. Esas son las katas.&lt;/p>
&lt;h3 id="cual-es-el-objetivo-de-una-kata-que-deberiamos-tener-al-final">¿Cuál es el objetivo de una kata? ¿Qué deberíamos tener al final?
&lt;a class="heading-anchor" href="#cual-es-el-objetivo-de-una-kata-que-deberiamos-tener-al-final" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Las katas existen para que los desarrolladores obtengamos los mismos beneficios que practicar en otras profesiones. Son ejercicios simples y artificiales que permiten experimentar y aprender sin la presión de producción.&lt;/p>
&lt;blockquote>
&lt;p>No hay respuestas correctas o incorrectas en ninguna kata de software: el beneficio viene del proceso, no del resultado.&lt;/p>
&lt;/blockquote>
&lt;h3 id="consejos">Consejos
&lt;a class="heading-anchor" href="#consejos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Cuando resuelvas una kata, vuelve a intentarla en unas semanas o meses.&lt;/li>
&lt;li>Explora nuevas soluciones. Sé creativo y no te apresures.&lt;/li>
&lt;li>En grupo, no es una competición para ver quién logra más.&lt;/li>
&lt;li>El foco debe estar en el proceso, nunca en el resultado.&lt;/li>
&lt;li>El verdadero valor de cualquier kata son los aprendizajes que obtendréis después de hablar y compartir experiencias.&lt;/li>
&lt;/ul>
&lt;p>Puedes encontrar muchas katas en Internet. Por ejemplo:&lt;/p>
&lt;ul>
&lt;li>&lt;a rel="external" href="http://codekata.com">http://codekata.com&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://codingdojo.org/kata">https://codingdojo.org/kata&lt;/a>&lt;/li>
&lt;li>&lt;a rel="external" href="https://github.com/gamontal/awesome-katas">https://github.com/gamontal/awesome-katas&lt;/a>&lt;/li>
&lt;/ul>
&lt;hr />
&lt;h3 id="tdd-es-mas-un-flujo-de-trabajo-que-un-diseno">TDD es más un flujo de trabajo que un diseño
&lt;a class="heading-anchor" href="#tdd-es-mas-un-flujo-de-trabajo-que-un-diseno" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;blockquote>
&lt;p>“TDD es una herramienta de diseño.” Eso es lo que Sandro dijo durante años. Pero ya no. Tras trabajar con diferentes equipos y organizaciones, y observar cómo trabaja él mismo, Sandro cambió de opinión sobre el rol de TDD en el diseño de software.&lt;/p>
&lt;/blockquote>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/KyFVA4Spcgg"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;p>TDD en pocas palabras; se trata del ritmo.&lt;/p>
&lt;ol>
&lt;li>Especifica lo que quieres.&lt;/li>
&lt;li>Hazlo funcionar.&lt;/li>
&lt;li>Hazlo mejor.&lt;/li>
&lt;/ol>
&lt;hr />
&lt;h2 id="kent-beck">Kent Beck
&lt;a class="heading-anchor" href="#kent-beck" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;blockquote class="twitter-tweet">&lt;p lang="en" dir="ltr">1. Change the code as usual&lt;br>2. Write a test that only passes after the change&lt;br>3. Revert to before 1&lt;br>4. Type the test again (copy/paste is cheating &amp;amp; invalidates the warranty of the exercise)&lt;br>5. Make it compile by changing the code&lt;br>6. See it fail&lt;br>7. Change the code to make it pass&lt;/p>&amp;mdash; Kent Beck 🌻 (@KentBeck) &lt;a href="https://twitter.com/KentBeck/status/1421257650113634304?ref_src=twsrc%5Etfw">July 30, 2021&lt;/a>&lt;/blockquote> &lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8">&lt;/script>
&lt;hr />
&lt;p>Imágenes originales de &lt;a rel="external" href="https://x.com/evrtrabajo">Emmanuel Valverde Ramos&lt;/a>.&lt;/p></content></entry><entry xml:lang="es"><title>Mockear o No Mockear</title><subtitle>Cómo escapar del infierno del mocking</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><published>2021-01-11T00:00:00+00:00</published><updated>2021-01-11T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/to-mock-or-not-to-mock/"/><id>https://chemaclass.com/es/blog/to-mock-or-not-to-mock/</id><summary type="html">Mockear es útil, pero 'qué mockear' suele resultar más complicado de lo esperado si no tratas esto con cuidado.</summary><content type="html">&lt;p>Mockear es útil, pero “qué mockear” suele resultar más complicado de lo esperado si no tratas esto con cuidado.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h4 id="como-escapar-del-infierno-del-mocking">Cómo escapar del infierno del mocking
&lt;a class="heading-anchor" href="#como-escapar-del-infierno-del-mocking" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;p>¿Qué pasa realmente cuando creamos un mock? ¿Qué tipos hay? ¿Es bueno o malo mockear? Como siempre, depende del contexto. Aquí veremos las situaciones principales: cuándo mockear, cuándo no hacerlo, y sobre todo por qué.&lt;/p>
&lt;h2 id="que-pasa-cuando-mockeas-algo">¿Qué pasa cuando mockeas algo?
&lt;a class="heading-anchor" href="#que-pasa-cuando-mockeas-algo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Primero, deberíamos definir qué es un mock:&lt;/p>
&lt;blockquote>
&lt;p>En un test unitario, los objetos mock pueden simular el comportamiento de objetos reales complejos y por lo tanto son útiles cuando es impracticable o imposible incorporar un objeto real en un test unitario.&lt;/p>
&lt;/blockquote>
&lt;p>Mockear tiene sentido en &lt;em>testing unitario&lt;/em>. Un test de integración pasa por la implementación real, verificando cómo interactúan varias unidades. Estos tests sí pueden hablar con la BD o el sistema de archivos.
Partimos de esta base: &lt;em>un test unitario es rápido, determinista, no depende de recursos externos y no requiere contexto especial para ejecutarse&lt;/em>.&lt;/p>
&lt;p>Los mocks cumplen el contrato de la &lt;em>interfaz&lt;/em>. Nos permiten testear funcionalidad sin invocar clases colaboradoras complejas.&lt;/p>
&lt;p>Un mock es un doble de test que sustituye la implementación real. Además, puede verificar cómo el código bajo test lo utilizó durante la ejecución.&lt;/p>
&lt;blockquote>
&lt;p>Recomiendo encarecidamente que leas este post si quieres entrar en los detalles de por qué &lt;a rel="external" href="https://medium.com/javascript-scene/mocking-is-a-code-smell-944a70c90a6a">Mockear es un code smell&lt;/a> (Temas como estos: ¿Qué es un mock? ¿Qué es un test unitario? ¿Qué es la cobertura de tests? ¿Qué es el acoplamiento fuerte? ¿Qué causa el acoplamiento fuerte? ¿Qué tiene que ver la composición con el mocking? ¿Cómo eliminamos el acoplamiento? ¡y más!)&lt;/p>
&lt;/blockquote>
&lt;h2 id="el-problema-con-mockear">El problema con mockear
&lt;a class="heading-anchor" href="#el-problema-con-mockear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Cuando mockeas, anulas la lógica de la clase mockeada. La lógica real queda oculta, y ahí es donde los bugs se esconden. Ten en cuenta que:&lt;/p>
&lt;ul>
&lt;li>
&lt;p>El mock puede tener atributos, métodos o argumentos que el objeto real no tiene.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Los &lt;em>valores de retorno del mock pueden diferir de los reales&lt;/em>. Por ejemplo, puede devolver un tipo distinto con atributos diferentes.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Los &lt;em>efectos secundarios y comportamiento del mock pueden diferir del objeto real&lt;/em>. Quizás el mock no lanza una excepción que el objeto real sí lanzaría.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="alternativas-a-mockear">Alternativas a mockear
&lt;a class="heading-anchor" href="#alternativas-a-mockear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>“¿Estás diciendo que mockear es malo y no deberíamos mockear?” No.&lt;/p>
&lt;p>Depende de lo que estés “anulando”.&lt;/p>
&lt;ul>
&lt;li>¿Es tu lógica de dominio de negocio lo que estás mockeando? Entonces está mal.&lt;/li>
&lt;li>¿Es la conexión a la BD lo que estás mockeando? Entonces está bien.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Depende del contexto de la lógica y dónde pertenece esa lógica.&lt;/p>
&lt;/blockquote>
&lt;p>¿Es parte de tu lógica de dominio de negocio? Entonces no deberías mockearla sino instanciarla.&lt;/p>
&lt;p>¿Es una dependencia de infraestructura como conexión a BD, sistema de archivos, red, o cualquier servicio externo que no tiene que ver con tu dominio de negocio? Entonces &lt;em>mockéala usando abstracciones/interfaces&lt;/em>.&lt;/p>
&lt;p>La interfaz es el &lt;em>contrato entre tu lógica de dominio y sus dependencias de infraestructura&lt;/em>.
Imagina lo fácil que es testear tu dominio instanciándolo y llamando a sus métodos con diferentes argumentos, todo bajo tu control total.&lt;/p>
&lt;h2 id="algunos-trucos">Algunos trucos
&lt;a class="heading-anchor" href="#algunos-trucos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Cuando estés escribiendo un test unitario:&lt;/p>
&lt;ul>
&lt;li>Intenta instanciar tus clases primero.&lt;/li>
&lt;li>Evita mockear clases concretas. Escribí un artículo exclusivamente sobre esto:
fomentando &lt;a rel="external" href="https://medium.com/swlh/final-classes-in-php-9174e3e2747e">clases finales&lt;/a> e interfaces.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Mockea interfaces. Instancia clases concretas.&lt;/p>
&lt;/blockquote>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/RbSqXFUfRMU"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div>
&lt;p>“El uso excesivo de mocks lleva a código legacy.” - Philippe Boargau&lt;/p>
&lt;h3 id="como-podemos-evitar-el-mocking-excesivo">¿Cómo podemos evitar el mocking excesivo?
&lt;a class="heading-anchor" href="#como-podemos-evitar-el-mocking-excesivo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Favorece el estado inmutable sobre el estado mutable.&lt;/li>
&lt;li>Haz las dependencias explícitas.&lt;/li>
&lt;li>Programa hacia una interfaz, no hacia una implementación.&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="/images/blog/2021-01-11/footer.webp" alt="mockea interfaces, instancia clases concretas" />&lt;/p>
&lt;hr />
&lt;h4 id="referencias">Referencias
&lt;a class="heading-anchor" href="#referencias" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ul>
&lt;li>&lt;a rel="external" href="https://medium.com/javascript-scene/mocking-is-a-code-smell-944a70c90a6a">Mocking is a code smell&lt;/a> - Eric Elliott&lt;/li>
&lt;li>&lt;a rel="external" href="https://blog.cleancoder.com/uncle-bob/2014/05/10/WhenToMock.html">When to mock&lt;/a> &amp;amp; &lt;a rel="external" href="https://blog.cleancoder.com/uncle-bob/2017/05/05/TestDefinitions.html">Test Definitions&lt;/a> - Uncle Bob&lt;/li>
&lt;li>&lt;a rel="external" href="https://matthiasnoback.nl/2018/09/final-classes-by-default-why/">Final classes by default&lt;/a> - Matthias Noback&lt;/li>
&lt;li>&lt;a rel="external" href="https://www.seanh.cc/2017/03/17/the-problem-with-mocks/">The problem with mocks&lt;/a> - Sean Hammond&lt;/li>
&lt;li>&lt;a rel="external" href="https://www.artima.com/weblogs/viewpost.jsp?thread=126923">A Set of Unit Testing Rules&lt;/a> - Michael Feathers&lt;/li>
&lt;/ul></content></entry><entry xml:lang="es"><title>Testeando Código Legacy de Forma Efectiva</title><subtitle>Cómo escribir tests adecuados para código ya escrito</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><published>2020-08-17T00:00:00+00:00</published><updated>2020-08-17T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/testing-effectively-legacy-code/"/><id>https://chemaclass.com/es/blog/testing-effectively-legacy-code/</id><summary type="html">Cómo escribir tests de caracterización para código legacy y refactorizar de forma segura sin romper el comportamiento existente.</summary><content type="html">&lt;p>Estos tests también se conocen como tests de caracterización.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;blockquote>
&lt;p>Un test de caracterización describe el comportamiento real de una pieza de software existente, y por lo tanto protege el
comportamiento existente del código legacy contra cambios no intencionados mediante testing automatizado. Este término fue acuñado por &lt;a href="/es/readings/working-effectively-with-legacy-code/">Michael Feathers&lt;/a>.&lt;/p>
&lt;/blockquote>
&lt;p>Permiten y proporcionan una red de seguridad para extender y refactorizar código que no tiene tests adecuados. Se puede
escribir un test que afirme que la salida del código legacy coincide con el resultado observado para las entradas dadas.&lt;/p>
&lt;h2 id="como-empezar">¿Cómo empezar?
&lt;a class="heading-anchor" href="#como-empezar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Estos son mis aprendizajes un año después de
leer &lt;a href="/es/readings/working-effectively-with-legacy-code/">Working Effectively with Legacy Code&lt;/a> y aplicarlo a los
diferentes proyectos en los que he trabajado desde entonces.&lt;/p>
&lt;h3 id="1-que-quieres-testear">1. ¿Qué quieres testear?
&lt;a class="heading-anchor" href="#1-que-quieres-testear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Averigua las aserciones. Crea un archivo de test para tu clase, y un método de test para la función que quieres testear.
Pista:&lt;/p>
&lt;ul>
&lt;li>Si tienes el siguiente método &lt;code>applySomeLogic(): ReturnType&lt;/code>,&lt;/li>
&lt;li>el test que podrías escribir es &lt;code>test_apply_some_logic(): void&lt;/code>.&lt;/li>
&lt;/ul>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogic&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> private&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> DependencyInterface&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> dependencyInterface&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> private&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ConcreteDependency&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> concrete&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> __construct&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> DependencyInterface dependencyInterface&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> ConcreteDependency concrete&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> )&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">dependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> dependencyInterface&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">concrete&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> concrete&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span>Input input&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ReturnType&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> caja negra responsable de crear un ReturnType&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> basado en el Input dado&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> return&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> Quiero afirmar que &amp;quot;aplicando alguna lógica&amp;quot;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> de MyBusinessLogic con el Input dado&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> recibiré un ReturnType concreto con un&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> cierto valor como su propiedad. Algo como:&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> assertEquals&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expected&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="2-instancia-la-clase-concreta-final-que-quieres-testear">2. Instancia la clase concreta/final que quieres testear.
&lt;a class="heading-anchor" href="#2-instancia-la-clase-concreta-final-que-quieres-testear" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>No mockees tus clases concretas. Especialmente tu dominio de negocio. Mockea solo interfaces. De lo contrario, puedes estar ocultando
bugs sin querer (¡con tests verdes/pasando!). Trata tus &lt;a href="/es/blog/final-classes">clases de dominio de negocio como finales&lt;/a>.&lt;/p>
&lt;p>O mockea la interfaz o instancia una clase anónima si quieres crear un Stub:&lt;/p>
&lt;blockquote>
&lt;p>Los Stubs proporcionan respuestas a llamadas hechas durante el test, normalmente sin responder a nada fuera de lo programado para el test.&lt;/p>
&lt;/blockquote>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createMock&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">DependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">class&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> )&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> O&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> FakeDependency&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> )&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> //&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ...&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;blockquote>
&lt;p>Donde &lt;code>FakeDependency&lt;/code> es una implementación concreta de &lt;code>DependencyInterface&lt;/code> con “datos/implementación falsos” ya preparados que solo es útil para propósitos de testing.&lt;/p>
&lt;/blockquote>
&lt;h3 id="3-llama-al-metodo-de-esa-clase-proporcionando-la-entrada-deseada">3. Llama al método de esa clase proporcionando la entrada deseada.
&lt;a class="heading-anchor" href="#3-llama-al-metodo-de-esa-clase-proporcionando-la-entrada-deseada" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>La salida será determinada por el estado inicial de la clase de lógica de negocio que queremos testear MÁS los argumentos
de entrada que estamos usando.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Input&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);">returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="4-afirma-la-salida-con-el-valor-esperado">4. Afirma la salida con el valor esperado.
&lt;a class="heading-anchor" href="#4-afirma-la-salida-con-el-valor-esperado" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Del paso 1 necesitas saber qué quieres. Aplica la(s) aserción(es) ahora.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createMock&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">DependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">::&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">class&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;span>)&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> )&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Input&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">/*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> assertEquals&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expected&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> returnType&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="5-puede-que-quieras-afirmar-diferentes-valores-esperados">5. Puede que quieras afirmar diferentes valores esperados.
&lt;a class="heading-anchor" href="#5-puede-que-quieras-afirmar-diferentes-valores-esperados" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Puedes proporcionar fácilmente diferentes argumentos a tu lógica de negocio ya sea a través de la construcción de la lógica o diferentes
argumentos dados. Para hacerlo, usa la anotación @dataProvider. El método “dataProvider” debe ser público y devolver cualquier iterable.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);">final&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> class&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> MyBusinessLogicTest&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> extends&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> TestCase&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>{&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> /**&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> @dataProvider providerApplySomeLogic &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> test_apply_some_logic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> array concreteMapping&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> string argInput&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> string expectedValue&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> )&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> void&lt;/span>&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> MyBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createMock&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">DependencyInterface&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">class&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> ConcreteDependency&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">concreteMapping&lt;/span>&lt;span>)&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6A737D, #6A737D);"> /*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> )&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> new&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Input&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">argInput&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> /*&lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);"> ... &lt;/span>&lt;span style="color: light-dark(#6A737D, #6A737D);">*/&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);"> actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);"> assertEquals&lt;/span>&lt;span>(&lt;/span>&lt;span>$&lt;/span>&lt;span>expectedValue&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> public&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> function&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);"> providerApplySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">:&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> Generator&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> {&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> yield&lt;/span>&lt;span> [&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">concreteMapping&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">value&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>]&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">argInput&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">something&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expectedValue&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expected-value-A&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> ]&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#D73A49, #F97583);"> yield&lt;/span>&lt;span> [&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">concreteMapping&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span> [&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">key2&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">value2&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>]&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">argInput&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">something-else&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expectedValue&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&amp;gt;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);"> &amp;#39;&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">expected-value-B&lt;/span>&lt;span style="color: light-dark(#032F62, #9ECBFF);">&amp;#39;&lt;/span>&lt;span>,&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> ]&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span> }&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;h3 id="por-ultimo-limpia-lo-que-hiciste">Por último: limpia lo que hiciste.
&lt;a class="heading-anchor" href="#por-ultimo-limpia-lo-que-hiciste" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Sí, limpia los tests. Merecen estar tan limpios como tu código de producción. De lo contrario, se pudrirán con el tiempo y
¡permanecerán sucios para tus compañeros y tu yo futuro!&lt;/p>
&lt;p>Por ejemplo, puedes aplicar el refactoring extract method para mover los detalles de implementación (de la creación de los
diferentes objetos) y mantener el mismo nivel de abstracción mientras lees el código del test.&lt;/p>
&lt;pre class="giallo" style="color-scheme: light dark; color: light-dark(#24292E, #E1E4E8); background-color: light-dark(#FFFFFF, #24292E);">&lt;code data-lang="php">&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);">myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createBusinessLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">concreteMapping&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> this&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">createInput&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">argInput&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#005CC5, #79B8FF);">actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);"> =&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> myBusinessLogic&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">applySomeLogic&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">input&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>
&lt;span class="giallo-l">&lt;span style="color: light-dark(#6F42C1, #B392F0);">assertEquals&lt;/span>&lt;span>(&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);">expectedValue&lt;/span>&lt;span>,&lt;/span>&lt;span style="color: light-dark(#005CC5, #79B8FF);"> actual&lt;/span>&lt;span style="color: light-dark(#D73A49, #F97583);">.&lt;/span>&lt;span style="color: light-dark(#6F42C1, #B392F0);">getProperty&lt;/span>&lt;span>(&lt;/span>&lt;span>)&lt;/span>&lt;span>)&lt;/span>&lt;span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>
&lt;p>Por supuesto, todo depende del contexto. ¿Realmente tiene sentido extraer a un método privado
createBusinessLogic() o incluso createInput()? Bueno, eso depende de ti. Depende del número de líneas y, lo más
importante, del nivel de abstracción que pertenece a ese contexto.&lt;/p>
&lt;blockquote>
&lt;p>Solo recuerda: mantén tus métodos pequeños.&lt;/p>
&lt;/blockquote>
&lt;p>Ahora puedes refactorizar el código de producción que cubriste con tests sin ese miedo a romperlo.&lt;/p>
&lt;hr />
&lt;h3 id="todo-junto">Todo junto
&lt;a class="heading-anchor" href="#todo-junto" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;script src="https://gist.github.com/Chemaclass&amp;#x2F;07704606fcb337dbb0881c94197c329e.js">&lt;/script>
&lt;script src="https://gist.github.com/Chemaclass&amp;#x2F;9f7f96242153b696b3f8da5c7fa80461.js">&lt;/script>
&lt;hr />
&lt;h2 id="el-codigo-legacy-es-codigo-sin-tests">El código legacy es código sin tests
&lt;a class="heading-anchor" href="#el-codigo-legacy-es-codigo-sin-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>&lt;img src="/images/blog/2020-08-17/footer.jpg" alt="el código legacy es código sin tests" />&lt;/p>
&lt;p>Por supuesto, hay mucho más que aprender
sobre &lt;a href="/es/readings/working-effectively-with-legacy-code/">testing y trabajo con código legacy&lt;/a>. De hecho, especialmente cuando
tratamos con código legacy, encontrarás situaciones donde el código está acoplado de alguna manera que podrías querer mockear
tus clases concretas porque no hay interfaz (todavía) para ello.&lt;/p>
&lt;p>Este libro te presenta muchas técnicas sobre cuándo, por qué, dónde y cómo puedes aplicar estos cambios.&lt;/p>
&lt;blockquote>
&lt;p>Cuando trabajas con código necesitas &lt;strong>retroalimentación&lt;/strong>. La retroalimentación automatizada es la mejor. Por lo tanto, esto es lo primero que necesitas hacer: escribir los tests.&lt;/p>
&lt;/blockquote>
&lt;h3 id="primero-anade-tests-luego-haz-tus-cambios">Primero, añade tests, luego haz tus cambios.
&lt;a class="heading-anchor" href="#primero-anade-tests-luego-haz-tus-cambios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;h4 id="cambia-la-menor-cantidad-de-codigo-posible-para-poner-los-tests-en-su-lugar-con-la-receta">Cambia la menor cantidad de código posible para poner los tests en su lugar con la receta:
&lt;a class="heading-anchor" href="#cambia-la-menor-cantidad-de-codigo-posible-para-poner-los-tests-en-su-lugar-con-la-receta" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h4>
&lt;ol>
&lt;li>Identifica “puntos de cambio” para romper las dependencias de tu código.&lt;/li>
&lt;li>Rompe las dependencias.&lt;/li>
&lt;li>Escribe los tests.&lt;/li>
&lt;li>Haz tus cambios.&lt;/li>
&lt;li>Refactoriza.&lt;/li>
&lt;/ol>
&lt;hr />
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/wRtJRkRIa2s"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>El Arte del Refactoring</title><subtitle>Cuándo, cómo y por qué</subtitle><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2020-06-28T00:00:00+00:00</published><updated>2020-06-28T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/the-art-of-refactoring/"/><id>https://chemaclass.com/es/blog/the-art-of-refactoring/</id><summary type="html">Si ves algo, en el ámbito de tu tarea actual, que puede mejorarse fácilmente, mejóralo. Y si tienes alguna pregunta al respecto, pregunta.</summary><content type="html">&lt;p>Si ves algo, en el ámbito de tu tarea actual, que puede mejorarse fácilmente, mejóralo. Y si tienes alguna pregunta al respecto, pregunta.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="que-es-el-refactoring">¿Qué es el refactoring?
&lt;a class="heading-anchor" href="#que-es-el-refactoring" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Refactoring significa mejorar tu código. Puede ser renombrar una variable, extraer líneas en un método privado, o separar responsabilidades de una clase en varias.&lt;/p>
&lt;p>El refactoring demuestra que te importa lo que haces como profesional. Es un tema controvertido desde hace tiempo. Pero eso no debería frenarnos de mejorar la calidad del sistema.&lt;/p>
&lt;h2 id="cuando-y-como-refactorizar">¿Cuándo y cómo refactorizar?
&lt;a class="heading-anchor" href="#cuando-y-como-refactorizar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Siempre. Dentro del ámbito de tu tarea actual, a menos que sea una tarea planificada específicamente para refactoring de arquitectura.&lt;/p>
&lt;blockquote>
&lt;p>El refactoring debería ser parte del trabajo diario, no una tarea separada.&lt;/p>
&lt;/blockquote>
&lt;p>No necesitamos pedir permiso para refactorizar. ¿Acaso pedimos permiso para hacer nuestro mejor trabajo?&lt;/p>
&lt;p>Para refactorizar bien, la intención debe estar clara. ¿Qué queremos lograr y cómo? El pair programming (o incluso el “pair thinking”) ayuda porque sincroniza dos cerebros y fomenta mejor comprensión mutua.&lt;/p>
&lt;p>Refactorizar de forma colaborativa es fundamental en equipo. No debería ser tabú. Al contrario: ayuda a unificar objetivos y dirección de calidad del código.&lt;/p>
&lt;h3 id="algunos-consejos-sobre-el-como">Algunos consejos sobre el “cómo”
&lt;a class="heading-anchor" href="#algunos-consejos-sobre-el-como" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Buscamos mejora continua, pero…&lt;/p>
&lt;ul>
&lt;li>
&lt;p>Si tus cambios generan más ruido que ayuda, para. Piensa si valen la pena en el estado actual del sistema. Quizás no es el momento. Quizás estás contaminando el diff con cambios fuera del ámbito. O quizás es demasiado grande para tu tarea actual. En ese caso, mejor crear una tarea de seguimiento.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>Si el refactoring es necesario antes de empezar tu tarea, hazlo primero.&lt;/p>
&lt;/li>
&lt;/ul>
&lt;p>Refactorizamos para aumentar productividad: código más legible es código más fácil de entender.&lt;/p>
&lt;h3 id="testing">Testing
&lt;a class="heading-anchor" href="#testing" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Necesitas un buen conjunto de tests cubriendo la lógica que vas a cambiar. Sin tests, refactorizar es arriesgado. Por lo general, cuanto más fácil es testear algo, más fácil es reemplazarlo o eliminarlo.&lt;/p>
&lt;p>Puedes leer más sobre cómo el testing está relacionado con la calidad aquí.&lt;/p>
&lt;h2 id="por-que-hacerlo">¿Por qué hacerlo?
&lt;a class="heading-anchor" href="#por-que-hacerlo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>¿No querrías un sistema mejor con el tiempo?&lt;/p>
&lt;p>El software no es como el vino: no mejora solo. Si quieres un sistema mejor, tienes que trabajar para conseguirlo.&lt;/p>
&lt;p>&lt;img src="/images/blog/2020-06-28/footer.webp" alt="el refactoring como mejora continua" />&lt;/p></content></entry><entry xml:lang="es"><title>Clases Final en PHP | Java | Cualquiera</title><subtitle>Final, o no final, esa es la cuestión</subtitle><category term="php" scheme="https://chemaclass.com/tags/php/" label="Php"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><published>2020-06-06T00:00:00+00:00</published><updated>2020-06-06T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/final-classes/"/><id>https://chemaclass.com/es/blog/final-classes/</id><summary type="html">Contratos claros, efectos secundarios aislados, testeabilidad, baja complejidad y carga cognitiva, fluidez del código y confianza en ti mismo.</summary><content type="html">&lt;p>Contratos claros, efectos secundarios aislados, testeabilidad, baja complejidad y carga cognitiva, fluidez del código y confianza en ti mismo.&lt;/p>
&lt;span id="continue-reading">&lt;/span>&lt;h2 id="motivacion">Motivación
&lt;a class="heading-anchor" href="#motivacion" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="reduce-la-visibilidad-al-minimo">Reduce la visibilidad al mínimo
&lt;a class="heading-anchor" href="#reduce-la-visibilidad-al-minimo" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Cuando una clase es &lt;code>final&lt;/code>, no puede ser extendida. Esto la hace más legible y te asegura que la lógica está limitada a esa clase.&lt;/p>
&lt;h3 id="fomenta-composicion-sobre-herencia">Fomenta “composición sobre herencia”
&lt;a class="heading-anchor" href="#fomenta-composicion-sobre-herencia" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El Principio Abierto-Cerrado dice: abierto para extensión, cerrado para modificación.&lt;/p>
&lt;p>Si decides crear una herencia (por una buena razón, de la que deberías ser consciente), simplemente quita &lt;code>final&lt;/code> y listo.&lt;/p>
&lt;p>Cuando por defecto no puedes extender una clase, te fuerzas a pensar en composición en lugar de herencia.&lt;/p>
&lt;h2 id="por-que-esta-clase-no-es-final">¿Por qué esta clase no es final?
&lt;a class="heading-anchor" href="#por-que-esta-clase-no-es-final" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Si preferimos composición sobre herencia, deberíamos evitar la herencia tanto como sea posible. La herencia se usa mal a menudo en POO.&lt;/p>
&lt;h3 id="un-concepto-mal-entendido">Un concepto mal entendido
&lt;a class="heading-anchor" href="#un-concepto-mal-entendido" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Cuando nos enseñaron POO, normalmente empezamos con el ejemplo clásico de herencia.&lt;/p>
&lt;p>Pero cuando Alan Kay creó Smalltalk, la herencia no era el concepto principal. Lo principal era el paso de mensajes: enviar mensajes a objetos que encapsulan datos y lógica, cambiando comportamiento mediante diferentes objetos. Eso es composición. La herencia se hizo tan popular que terminó eclipsando a la composición.&lt;/p>
&lt;h3 id="beneficios">Beneficios
&lt;a class="heading-anchor" href="#beneficios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Contratos claros.&lt;/strong> Usar interfaces te obliga a pensar en comunicación entre objetos.&lt;/li>
&lt;li>&lt;strong>Código aislado, sin efectos secundarios.&lt;/strong> Inyectar solo interfaces elimina efectos secundarios molestos.&lt;/li>
&lt;li>&lt;strong>Testeabilidad.&lt;/strong> Mockear interfaces es muy fácil.&lt;/li>
&lt;li>&lt;strong>Complejidad manejable.&lt;/strong> Todo aislado significa menos cambios en cascada.&lt;/li>
&lt;li>&lt;strong>Baja carga cognitiva.&lt;/strong> Menos complejidad, más foco en lo importante.&lt;/li>
&lt;li>&lt;strong>Flexibilidad.&lt;/strong> Sin acoplamiento innecesario, mover código es más fácil.&lt;/li>
&lt;li>&lt;strong>Confianza.&lt;/strong> Testear código aislado te da seguridad para cambiarlo.&lt;/li>
&lt;/ul>
&lt;h2 id="composicion-sobre-herencia">Composición sobre herencia
&lt;a class="heading-anchor" href="#composicion-sobre-herencia" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;p>Si necesitas reconfigurar un objeto, cambiar partes de un algoritmo o reescribir parte de la implementación, considera crear una nueva clase en lugar de sobreescribir una existente.&lt;/p>
&lt;p>¿Necesitas representar una jerarquía donde las subclases sustituyen a las clases padre? Esta sería la situación clásica donde podrías usar herencia. Aun así, el resultado suele ser mejor si heredas de interfaces abstractas, no de clases concretas.&lt;/p>
&lt;h3 id="que-hacer-en-su-lugar">Qué hacer en su lugar
&lt;a class="heading-anchor" href="#que-hacer-en-su-lugar" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Usa interfaces para definir contratos entre clases.&lt;/li>
&lt;li>Usa clases finales para implementar esas interfaces.&lt;/li>
&lt;li>Usa composición (inyección de dependencias por constructor) para unir las piezas.&lt;/li>
&lt;/ul>
&lt;blockquote>
&lt;p>Interfaces -&amp;gt; Clases finales -&amp;gt; Composición&lt;/p>
&lt;/blockquote>
&lt;p>&lt;img src="/images/blog/2020-06-06/footer.webp" alt="interfaces, clases finales y composición" />&lt;/p></content></entry><entry xml:lang="es"><title>El Arte del Testing: Donde el Diseño se Encuentra con la Calidad</title><subtitle>Desde el punto de vista de un desarrollador de software</subtitle><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><published>2020-04-07T00:00:00+00:00</published><updated>2020-04-07T00:00:00+00:00</updated><author><name>
Chemaclass</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/blog/the-art-of-testing/"/><id>https://chemaclass.com/es/blog/the-art-of-testing/</id><summary type="html">Por qué deberías considerar el testing como parte de tu hábito diario de desarrollo y cómo está directamente vinculado a la calidad del software.</summary><content type="html">&lt;p>¿Por qué considerar el testing parte de tu desarrollo diario? Porque está directamente vinculado a la calidad del software.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;p>No voy a explicar las diferentes técnicas de testing ni las diferencias entre tests unitarios, de integración, funcionales o end-to-end.&lt;/p>
&lt;p>Me sigue sorprendiendo la falta de experiencia con testing en el mundo del software. Hay una ignorancia generalizada sobre buenas prácticas. Si has trabajado en varios proyectos y equipos, seguro que lo has visto.&lt;/p>
&lt;h3 id="testing-de-software">Testing de software
&lt;a class="heading-anchor" href="#testing-de-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Algunos patrones horribles que he visto (y hecho):&lt;/p>
&lt;ul>
&lt;li>Testear por testear: testear cada archivo individual, confundiéndolo con una “unidad”.&lt;/li>
&lt;li>Mockear cada clase, anulando la implementación real y creando comportamiento falso. Esto da una falsa sensación de cobertura.&lt;/li>
&lt;li>Acoplar código de producción con tests por todas partes. Imposible cambiar nada sin romper tests, aunque la funcionalidad siga funcionando.&lt;/li>
&lt;li>No testear nada porque “ya funciona, ¿para qué perder más tiempo?”&lt;/li>
&lt;/ul>
&lt;p>Una razón principal del testing es verificar el comportamiento esperado del software. Pero el testing puede (y debería) ser mucho más que eso.&lt;/p>
&lt;h3 id="diseno-de-software">Diseño de software
&lt;a class="heading-anchor" href="#diseno-de-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El diseño de software abarca desde algoritmos hasta arquitectura. Aunque estos dos niveles tienen necesidades distintas, comparten patrones comunes. Por ejemplo, el testing:&lt;/p>
&lt;blockquote>
&lt;p>Si es fácil de testear, probablemente será debido a un buen diseño.&lt;/p>
&lt;/blockquote>
&lt;h3 id="calidad-del-software">Calidad del software
&lt;a class="heading-anchor" href="#calidad-del-software" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Medir la calidad es difícil. Hay muchas métricas a considerar. Aun así, seguro que podemos estar de acuerdo en esto:&lt;/p>
&lt;blockquote>
&lt;p>Si aspiras a la calidad en tu software, mejor busca un buen diseño.&lt;/p>
&lt;/blockquote>
&lt;p>Testear significa “probar”. ¿Cuántas veces hemos abandonado tests por la complejidad de probar cierta lógica?&lt;/p>
&lt;p>El arte del testing consiste en usar los tests para contribuir al resultado final. Si usamos el testing a nuestro favor, según el contexto, mejoraremos la calidad del producto.&lt;/p>
&lt;p>Por tanto, el testing no solo verifica comportamiento. También guía el software hacia un mejor diseño.&lt;/p>
&lt;p>¿Deberíamos testear todo? Depende del contexto. Habrá situaciones donde los tests no aporten beneficio. Aun así, escribe código como si fuera a ser testeado.&lt;/p>
&lt;p>&lt;img src="/images/blog/2020-04-07/footer.webp" alt="código testeable y buen diseño" />&lt;/p>
&lt;blockquote>
&lt;p>El código testeable tiende a un mejor diseño y, por lo tanto, a mejor calidad.&lt;/p>
&lt;/blockquote></content></entry><entry xml:lang="es"><title>Trabajando con código legado</title><subtitle>Estrategias para trabajar con código heredado</subtitle><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><published>2019-07-01T00:00:00+00:00</published><updated>2019-07-01T00:00:00+00:00</updated><author><name>
Michael Feathers</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/working-effectively-with-legacy-code/"/><id>https://chemaclass.com/es/readings/working-effectively-with-legacy-code/</id><summary type="html">Estrategias prácticas para lidiar con grandes bases de código sin tests. Cómo añadir tests, romper dependencias y refactorizar con seguridad.</summary><content type="html">&lt;span id="continue-reading">&lt;/span>&lt;h2 id="que-es-codigo-legacy">¿Qué es código legacy?
&lt;a class="heading-anchor" href="#que-es-codigo-legacy" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;blockquote>
&lt;p>El código legacy es simplemente código sin tests.&lt;/p>
&lt;/blockquote>
&lt;h3 id="beneficios-de-los-tests">Beneficios de los tests
&lt;a class="heading-anchor" href="#beneficios-de-los-tests" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>El comportamiento es clave para entender los beneficios del testing:&lt;/p>
&lt;blockquote>
&lt;p>El comportamiento es lo más importante del software. Los usuarios dependen de él. Les gusta que añadamos funcionalidad (si es lo que querían), pero si cambiamos o rompemos comportamiento del que dependen, pierden la confianza.&lt;/p>
&lt;/blockquote>
&lt;h3 id="como-implementar-tests-en-bases-de-codigo-legacy">Cómo implementar tests en bases de código legacy
&lt;a class="heading-anchor" href="#como-implementar-tests-en-bases-de-codigo-legacy" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;p>Para cambiar código necesitas tests. Pero para añadir tests muchas veces tienes que cambiar código.&lt;/p>
&lt;p>El enfoque sugerido:&lt;/p>
&lt;ol>
&lt;li>Identificar puntos de cambio.&lt;/li>
&lt;li>Encontrar puntos de test.&lt;/li>
&lt;li>Romper dependencias.&lt;/li>
&lt;li>Escribir tests.&lt;/li>
&lt;li>Hacer cambios y refactorizar.&lt;/li>
&lt;/ol>
&lt;p>Un término útil es “&lt;strong>costura&lt;/strong>” (seam): &lt;strong>un lugar donde puedes cambiar el comportamiento sin editar ese código directamente&lt;/strong>. Como la costura en la ropa, donde dos partes se unen.
En software, &lt;strong>estos lugares suelen tener interfaces bien definidas&lt;/strong>. Puedes aprovecharlos para cambiar implementaciones con inyección de dependencias o mocking en tests.&lt;/p>
&lt;hr />
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/wRtJRkRIa2s"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry><entry xml:lang="es"><title>Código Limpio</title><subtitle>Manual de artesanía ágil de software</subtitle><category term="clean-code" scheme="https://chemaclass.com/tags/clean-code/" label="Clean Code"/><category term="software-design" scheme="https://chemaclass.com/tags/software-design/" label="Software Design"/><category term="testing" scheme="https://chemaclass.com/tags/testing/" label="Testing"/><category term="tdd" scheme="https://chemaclass.com/tags/tdd/" label="Tdd"/><category term="refactoring" scheme="https://chemaclass.com/tags/refactoring/" label="Refactoring"/><published>2016-05-01T00:00:00+00:00</published><updated>2016-05-01T00:00:00+00:00</updated><author><name>
Robert C. Martin</name></author><link rel="alternate" type="text/html" href="https://chemaclass.com/es/readings/clean-code/"/><id>https://chemaclass.com/es/readings/clean-code/</id><summary type="html">El código malo funciona, pero puede hundir a una empresa. Cada año se pierden horas y recursos por código mal escrito. Este libro te enseña a evitarlo.</summary><content type="html">&lt;p>El código malo puede funcionar, pero si no está limpio, puede hundir a una empresa. Cada año se pierden horas y recursos por culpa de código mal escrito. No tiene por qué ser así.&lt;/p>
&lt;span id="continue-reading">&lt;/span>
&lt;hr />
&lt;h2 id="resumen">Resumen
&lt;a class="heading-anchor" href="#resumen" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h2>
&lt;h3 id="capitulo-1-que-es-el-codigo-limpio">Capítulo 1: ¿Qué es el código limpio?
&lt;a class="heading-anchor" href="#capitulo-1-que-es-el-codigo-limpio" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>El código se puede medir como “bueno” o “malo” en una revisión, o por cuánto tiempo tardas en explicarlo.&lt;/li>
&lt;li>El código limpio es elegante, eficiente, legible, simple, sin duplicaciones y bien escrito.&lt;/li>
&lt;li>Tu código debe añadir valor al negocio.&lt;/li>
&lt;li>Al abrir un archivo fuente, el código limpio transmite calidad y se entiende fácilmente.&lt;/li>
&lt;li>Haz tu código limpio y legible para que cualquiera pueda entenderlo rápido. No hagas perder tiempo a otros.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-2-nombres-significativos">Capítulo 2: Nombres significativos
&lt;a class="heading-anchor" href="#capitulo-2-nombres-significativos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Los nombres de las clases, variables y métodos deben ser significativos e indicar claramente lo que hace un método o lo que es un atributo.&lt;/li>
&lt;li>Crea nombres pronunciables para facilitar la comunicación.&lt;/li>
&lt;li>Evita acrónimos y nombres confusos, que pueden llevar a conclusiones erróneas a cualquiera que lea el código.&lt;/li>
&lt;li>Usa nombres que reflejen el dominio del sistema, el contexto y los problemas que deben resolverse.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-3-funciones">Capítulo 3: Funciones
&lt;a class="heading-anchor" href="#capitulo-3-funciones" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Los métodos deben ser fáciles de leer y entender.&lt;/li>
&lt;li>Deben transmitir su intención.&lt;/li>
&lt;li>Deben ser pequeños: hasta 20 líneas.&lt;/li>
&lt;li>Deben hacer solo una cosa.&lt;/li>
&lt;li>Usa nombres que digan claramente qué hace el método.&lt;/li>
&lt;li>El número ideal de parámetros es cero, luego uno, luego dos.&lt;/li>
&lt;li>Evita tres parámetros; si los usas, justifícalo.&lt;/li>
&lt;li>Un &lt;code>Boolean&lt;/code> como parámetro indica que el método hace más de una cosa.&lt;/li>
&lt;li>Evita la duplicación.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-4-comentarios">Capítulo 4: Comentarios
&lt;a class="heading-anchor" href="#capitulo-4-comentarios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Cuando necesitas comentarios suele ser porque el código es malo.&lt;/li>
&lt;li>Si piensas escribir un comentario, mejor refactoriza el código.&lt;/li>
&lt;li>Los comentarios no salvan el código malo.&lt;/li>
&lt;li>El código debe explicarse por sí mismo.&lt;/li>
&lt;li>A veces los comentarios son útiles en ciertos lugares específicos.&lt;/li>
&lt;li>No expliques el código con comentarios. Usa nombres descriptivos de variables y métodos.&lt;/li>
&lt;li>Los comentarios pueden destacar la importancia de ciertos puntos.&lt;/li>
&lt;li>No escribas comentarios redundantes, inútiles o falsos.&lt;/li>
&lt;li>Para saber quién cambió qué y por qué, usa control de versiones.&lt;/li>
&lt;li>No comentes código sin usar. Elimínalo.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-5-formato">Capítulo 5: Formato
&lt;a class="heading-anchor" href="#capitulo-5-formato" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>El formato es una forma de comunicación entre desarrolladores.&lt;/li>
&lt;li>El código desordenado es difícil de leer.&lt;/li>
&lt;li>La legibilidad afecta a todos los cambios futuros.&lt;/li>
&lt;li>Las clases pequeñas son más fáciles de entender.&lt;/li>
&lt;li>Pon un límite de caracteres por línea (por ejemplo, 120).&lt;/li>
&lt;li>Mantén los conceptos relacionados cerca verticalmente para crear un flujo natural.&lt;/li>
&lt;li>Usa espacios entre operadores, parámetros y comas.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-6-objetos-y-estructuras-de-datos">Capítulo 6: Objetos y estructuras de datos
&lt;a class="heading-anchor" href="#capitulo-6-objetos-y-estructuras-de-datos" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Sigue la &lt;a rel="external" href="https://en.wikipedia.org/wiki/Law_of_Demeter">Ley de Demeter&lt;/a>:
&lt;ul>
&lt;li>Cada unidad debe tener solo conocimiento limitado sobre otras unidades: solo unidades “estrechamente” relacionadas con la unidad actual.&lt;/li>
&lt;li>Cada unidad solo debe hablar con sus amigos; no hables con extraños.&lt;/li>
&lt;li>Solo habla con tus amigos inmediatos.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>No hagas objetos tontos.&lt;/li>
&lt;li>Los objetos ocultan la abstracción de datos y exponen métodos que operan los datos.&lt;/li>
&lt;li>Las estructuras de datos exponen sus datos y no tienen métodos significativos.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-7-manejo-de-errores">Capítulo 7: Manejo de errores
&lt;a class="heading-anchor" href="#capitulo-7-manejo-de-errores" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Planifica el manejo de errores con cuidado.&lt;/li>
&lt;li>Cuando algo falla, hay que hacer que el sistema responda correctamente.&lt;/li>
&lt;li>Lanza excepciones en lugar de ocultarlas.&lt;/li>
&lt;li>Crea mensajes de error informativos: qué falló, dónde y, si es posible, por qué.&lt;/li>
&lt;li>Separa las reglas de negocio del manejo de errores.&lt;/li>
&lt;li>Evita devolver &lt;code>NULL&lt;/code>; devuelve un objeto vacío.&lt;/li>
&lt;li>Evita pasar &lt;code>NULL&lt;/code> a los métodos; puede causar &lt;code>NullPointerExceptions&lt;/code>.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-8-limites">Capítulo 8: Límites
&lt;a class="heading-anchor" href="#capitulo-8-limites" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Al usar código de terceros, encapsula las APIs para no exponer objetos externos.&lt;/li>
&lt;li>Haz tests de las APIs de terceros.&lt;/li>
&lt;li>Estudia la documentación y prueba la API antes de usarla.&lt;/li>
&lt;li>Conoce bien las características que vas a usar.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-9-tests-unitarios">Capítulo 9: Tests unitarios
&lt;a class="heading-anchor" href="#capitulo-9-tests-unitarios" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Asegúrate de que cada pieza de código hace lo que esperas.&lt;/li>
&lt;li>Sigue las &lt;a rel="external" href="https://en.wikipedia.org/wiki/Test-driven_development">leyes de TDD&lt;/a>:
&lt;ul>
&lt;li>No escribas código sin tener primero un test que falle.&lt;/li>
&lt;li>No escribas más tests de los necesarios para fallar.&lt;/li>
&lt;li>No escribas más código del necesario para pasar el test.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Mantén tus tests limpios.&lt;/li>
&lt;li>Los tests evolucionan junto con el código.&lt;/li>
&lt;li>Código sucio = tests difíciles de mantener.&lt;/li>
&lt;li>Usa la regla F.I.R.S.T:
&lt;ul>
&lt;li>&lt;strong>F&lt;/strong>ast: ejecución rápida.&lt;/li>
&lt;li>&lt;strong>I&lt;/strong>ndependent: independientes entre sí.&lt;/li>
&lt;li>&lt;strong>R&lt;/strong>epeatable: repetibles en cualquier entorno.&lt;/li>
&lt;li>&lt;strong>S&lt;/strong>elf-validating: auto-validantes.&lt;/li>
&lt;li>&lt;strong>T&lt;/strong>imely: escritos a tiempo.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Los tests son tan importantes como el código de producción.&lt;/li>
&lt;/ul>
&lt;h3 id="capitulo-10-clases">Capítulo 10: Clases
&lt;a class="heading-anchor" href="#capitulo-10-clases" title="Copy link" aria-label="Link to this section">#&lt;/a>
&lt;/h3>
&lt;ul>
&lt;li>Organiza las clases así:
&lt;ul>
&lt;li>Constantes públicas estáticas.&lt;/li>
&lt;li>Variables privadas estáticas.&lt;/li>
&lt;li>Variables de instancia privadas.&lt;/li>
&lt;li>Luego los métodos.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>El nombre de la clase debe reflejar su responsabilidad.&lt;/li>
&lt;li>Cada clase debe tener &lt;a rel="external" href="https://en.wikipedia.org/wiki/Single-responsibility_principle">una sola responsabilidad&lt;/a>: una razón para cambiar.&lt;/li>
&lt;li>Intenta describir la clase en una frase breve.&lt;/li>
&lt;li>Los métodos deben ser pequeños y con una sola responsabilidad.&lt;/li>
&lt;/ul>
&lt;hr />
&lt;p>Esta entrevista se basa en el libro de Uncle Bob “Código Limpio”. Repasan algunas guías que te ayudarán a ser mejor programador y exploran cómo los libros y tendencias actuales están moldeando el mundo del software.&lt;/p>
&lt;div style="position:relative;aspect-ratio:16/9;width:100%;">
&lt;iframe
src="https://www.youtube-nocookie.com/embed/QnmRpHFoYLk"
title="YouTube video"
width="560"
height="315"
loading="lazy"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
referrerpolicy="strict-origin-when-cross-origin"
style="position:absolute;inset:0;width:100%;height:100%;border:0;"
allowfullscreen>
&lt;/iframe>
&lt;/div></content></entry></feed>