<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Javier Aguirre</title>
    <description>The latest articles on Forem by Javier Aguirre (@javaguirre).</description>
    <link>https://forem.com/javaguirre</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F19872%2F3560ecb7-8e56-4de6-9c39-20ff747f68e1.jpg</url>
      <title>Forem: Javier Aguirre</title>
      <link>https://forem.com/javaguirre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/javaguirre"/>
    <language>en</language>
    <item>
      <title>What I learned from recruiting for developer jobs</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Wed, 08 Sep 2021 09:00:00 +0000</pubDate>
      <link>https://forem.com/javaguirre/what-i-learned-from-recruiting-for-developer-jobs-278n</link>
      <guid>https://forem.com/javaguirre/what-i-learned-from-recruiting-for-developer-jobs-278n</guid>
      <description>&lt;p&gt;Recruiting, something many of us have suffered more than enjoyed due to the voracious, aggressive and competitive tech world.&lt;/p&gt;

&lt;p&gt;In several occasions candidates applying have asked me for feedback, here I compile the ideas they told me had found useful.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;We don’t need a PDF/paper CV, show how you work by sharing articles, your code on GitHub, your contributions on different blogging platforms, videos on YouTube.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Companies hiring get a great glimpse&lt;/strong&gt; of who you are if you can share it with the world.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26n6WywJyh39n1pBu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26n6WywJyh39n1pBu/giphy.gif" alt="" width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why
&lt;/h2&gt;

&lt;p&gt;Paper or PDF CVs are deprecated for many people, and It’s difficult to interact with them. I’ve been recruiting (not my main role) for four companies and I had been refining the job offers until We got to a level in which we can show our culture, honesty, and work to do through It. This has been possible thanks to other offers we liked that inspired us heavily into the direction we wanted.&lt;/p&gt;

&lt;p&gt;Due to that, the impact of the offers is usually high in terms of valid candidates, but still, there is a high number of candidates that are discarded very fast because they don’t show anything. Meaning they have a PDF with some information and no relevant information on LinkedIn, so you need to download the PDF to gather the relevant information for a candidate. It’s fine if you’re interested in 5, but if you are in 30 and don’t have an HR person to do it, It’s cumbersome and you leave people out that might be relevant.&lt;/p&gt;

&lt;p&gt;But due to this fact, a candidate is not very different from another, and you get the differences (sometimes) if you open all the PDFs.&lt;/p&gt;

&lt;h2&gt;
  
  
  We want to know how you work and what you know
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It’s difficult to differentiate from the rest if you just have a PDF CV&lt;/strong&gt; , no LinkedIn detailed information, or no GitHub or articles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pay for the thing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If you are on a LinkedIn job process, pay for the lower level subscription&lt;/strong&gt; , it gives you information about the position you’re applying to and you can adapt your information better to the offer. It’s not about lying, but about improving the communication of your personal brand.&lt;/p&gt;

&lt;h2&gt;
  
  
  We all have personal brands
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;If we want to choose better job positions, we all need to take care of our personal brand&lt;/strong&gt;. I realized that late since what I really liked was just programming and not taking care of my brand, but I learned on time. Take care of what you are communicating and showing (good and bad) in the networks you use professionally. Try to communicate what you do and know even if you don’t have a job. I hire some people on the spot just because of that. That shows proactivity and eagerness to learn which are two very important skills.&lt;/p&gt;

&lt;p&gt;Try to open source everything you can, even if you think is not worth noting, It always adds value. The same in terms of posting articles about something you learned, or even video.&lt;/p&gt;

&lt;p&gt;A video about yourself is a bonus, you learn so much from It in terms of communication and character.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/hsgN8oRJ7kjXf6JRih/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/hsgN8oRJ7kjXf6JRih/giphy.gif" alt="" width="480" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Community
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Nowadays developer communities can give you a lot of information on how the market goes&lt;/strong&gt; , what are the best companies to work on and most of all finding nice people to learn from. I meet the most interesting people in the Python Madrid group and I’m super happy to have been part of that community. It’s also very appealing and gives the same good proactivity and passion vibes companies would like in the people they hire.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/zPOErRpLtHWbm/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/zPOErRpLtHWbm/giphy.gif" alt="" width="240" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Participating in a Free Software/Open Source project is always very interesting. Even if it’s only helping with the documentation at the beginning, It’s a very relevant action to &lt;strong&gt;point your career in the direction you want&lt;/strong&gt;. For example, finding a project you like and It’s being used in a company you want to work on. Reading code from our favorite projects is also an amazing way of improving our coding skills and essential IMHO.&lt;/p&gt;

&lt;h2&gt;
  
  
  Targetting a company
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Check if they have &lt;a href="https://stackshare.com/"&gt;StackShare&lt;/a&gt; or find a way to look for what tech they use.&lt;/li&gt;
&lt;li&gt;Check if they have &lt;a href="https://github.com/wealize"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Check the relevant people in the company on LinkedIn, Send an Inmail message if they don’t have positions open, try to amaze them with something you’ve done.&lt;/li&gt;
&lt;li&gt;Take advantage of the possibilities we have nowadays!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical tests
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don’t be afraid, you already have a no for an answer&lt;/li&gt;
&lt;li&gt;Abstract functionality (reading &lt;a href="https://www.oreilly.com/library/view/clean-code-a/9780136083238/"&gt;Clean Code by Robert C. Martin&lt;/a&gt; is a good start)&lt;/li&gt;
&lt;li&gt;Automated testing (unit test, integration, e2e) is a must&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Interviews
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Nobody wants to listen to how bad your previous company was&lt;/li&gt;
&lt;li&gt;Talk about how would you be relevant in the position they are offering&lt;/li&gt;
&lt;li&gt;Try to give alternatives whenever there is something you don’t have (I don’t have Angular but I’ve worked with React and I could adapt…)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The more hints we give the company on how we work without even knowing us the better. The more proactivity and interest in what you do you transmit the more chances will be for you to get an interview.&lt;/p&gt;

&lt;p&gt;If you want to work remotely and a company to trust you, you can start showing it in what you do now without even starting to work with them. Show them autonomy and proactivity and that you are a &lt;a href="https://signalvnoise.com/posts/1430-hire-managers-of-one"&gt;Manager of One&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This was only what I’ve learned from being on both sides of the coin for years, but your path might be different than what I experienced. Let me know if that’s the case!&lt;/p&gt;

&lt;p&gt;Have a great day!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/jpoDZOyEg38F4cFFMi/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/jpoDZOyEg38F4cFFMi/giphy.gif" alt="" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>startup</category>
      <category>junior</category>
      <category>recruiting</category>
    </item>
    <item>
      <title>Qué he aprendido contratando desarrolladores</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Thu, 26 Aug 2021 09:00:00 +0000</pubDate>
      <link>https://forem.com/javaguirre/que-he-aprendido-contratando-desarrolladores-35k9</link>
      <guid>https://forem.com/javaguirre/que-he-aprendido-contratando-desarrolladores-35k9</guid>
      <description>&lt;p&gt;Procesos de reclutamiento, algo que muchos de nosotros hemos sufrido más que disfrutado por el voraz y agresivo/competitivo mundo en el que se mueve la tecnología.&lt;/p&gt;

&lt;p&gt;En varias ocasiones candidatos me han pedido feedback y aquí recopilo las ideas que normalmente les han servido de algo de lo que he aprendido.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Las empresas en general no necesitamos un CV de papel/PDF, sino ver cómo trabajas a través de los artículos, código en GitHub, contribuciones en distintas redes especializadas o blogs, incluso videos en YouTube.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Las empresas que contratan pueden tener una magnífica visión&lt;/strong&gt; de quién eres si compartes con el mundo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26n6WywJyh39n1pBu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26n6WywJyh39n1pBu/giphy.gif" alt="" width="720" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Por qué
&lt;/h2&gt;

&lt;p&gt;Los CVs en PDF o papel están desfasados para mucha gente, principalmente por la dificultad que se tiene para interactuar con la información contenida en ellos. He tenido la necesidad de reclutar en cuatro empresas y eso me ha obligado a ir refinando bastante las ofertas de trabajo que publicábamos.&lt;/p&gt;

&lt;p&gt;En los primeros procesos en los que participé no tenía ni idea de por dónde empezar y fue más una cuestión de contactos y de personas que estudiaron conmigo y en las que confiaba para hacerlo bien. Más adelante iteramos hacia la típica “lista de la compra” de recursos que había que cumplir y en poner un sueldo en mercado, en lo que la empresa busca. Posteriormente moverlo tímidamente por grupos de desarrollo como Python ES cumpliendo con las normas de compartir este tipo de ofertas en esos grupos.&lt;/p&gt;

&lt;p&gt;Tras unos cuantos procesos y tener un poco más de experiencia empecé a ver una tendencia en la industria que iba en la dirección, no de buscar un candidato, sino de centrarse completamente en las necesidades de éste y en hacer el trabajo atractivo y realista para él, entender cuál iba a ser el día a día. Los mejores artistas copian así que copié de las mejores ofertas que me encontré que reflejaban esta dirección, principalmente las últimas de Manfred o Audiense.&lt;/p&gt;

&lt;p&gt;Debido a esta búsqueda de la oferta más atractiva el impacto de las ofertas que publicamos ahora es mayor del que nunca había tenido anteriormente, a pesar de que el salario no es ni mucho menos el más alto que he podido ofrecer en una oferta.&lt;/p&gt;

&lt;p&gt;Desgraciadamente hay muchos que son descartados rápido principalmente porque tienen escasa información que compartir en un CV en PDF. Puede ser interesante revisar estos documentos concienzudamente si tienes cinco candidatos, pero si tienes cincuenta la cosa empieza a complicarse y los descartes son más rápidos y puede llegar a haber algún falso negativo.&lt;/p&gt;

&lt;p&gt;Muchos candidatos no son muy distintos de otros basándose únicamente en este documento y encontrar más información se hace muy difícil.&lt;/p&gt;

&lt;h2&gt;
  
  
  Queremos saber cómo trabajas y qué sabes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Es muy difícil diferenciarse si solo tenemos un CV en PDF&lt;/strong&gt; , un LinkedIn con poca información no actualizada, nada en GitHub y ningún artículo publicado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Paga para ganar
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Si estás en un proceso a través de LinkedIn, pagar por el plan más barato&lt;/strong&gt; te va a dar información sobre la posición a la que estás aplicando y puedes adaptar mejor lo que eres capaz de hacer a la oferta. No se trata de engañar, sino de mejorar la comunicación de tu marca personal y potenciar las cosas positivas que tienes y pueden dar valor en la posición que quieres conseguir.&lt;/p&gt;

&lt;h2&gt;
  
  
  Todos tenemos marca personal, lo queramos o no
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Si queremos una posición mejor en otra empresa, todos necesitamos cuidar nuestra marca personal&lt;/strong&gt;. Me di cuenta de esto tarde en mi carrera, solo me preocupaba mejorar técnicamente y seguir programando, pero en un momento me di cuenta de mi error. Es necesario cuidar lo que comunicamos y compartimos como todos sabemos (bueno y malo) en las redes que usamos profesionalmente. Es muy positivo comunicar lo que sabemos y en lo que estamos trabajando especialmente cuando estamos sin empleo o empezando nuestra carrera. En alguna ocasión he contratado a gente sin apenas experiencia solo por esa proactividad y ganas de participar y formarse que tenían, es una motivación muy poderosa.&lt;/p&gt;

&lt;p&gt;Intentar hacer software libre todo lo que se pueda, incluso si pensamos que no merece la pena lo que hemos hecho o es “malo”, siempre da valor. Lo mismo me ha ocurrido con conocimientos que iba adquiriendo, aunque fuese un detalle pequeño, si nadie había escrito sobre ello o se podía ahondar más creo que es positivo escribir sobre ello en público. Además cuando escribimos sobre algo profundizamos más y afianzamos conceptos, como cuando un profesor le enseña algo a un alumno, ambos aprenden.&lt;/p&gt;

&lt;p&gt;El video actualmente me parece una herramienta muy potente para comunicar y diferenciarse, aunque sean cortos, dan muchas más pinceladas de qué tipo de personas somos y de nuestra forma de comunicar y carácter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/hsgN8oRJ7kjXf6JRih/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/hsgN8oRJ7kjXf6JRih/giphy.gif" alt="" width="480" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comunidad
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Desde hace mucho tiempo las comunidades de desarrolladores nos pueden dar mucha información sobre cómo se está moviendo el mundo tecnológico&lt;/strong&gt; , cuáles son las mejores empresas en las que trabajar en cierta tecnología y sobretodo conocer a personas de las que aprender mucho. Conocí a las personas más interesantes en la comunidad de Python en Madrid y estoy muy contento de haber podido formar parte de esa gran comunidad. Te da una fuerza para continuar, una proactividad y una pasión en el aprendizaje que es difícil de encontrar de otra manera.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/zPOErRpLtHWbm/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/zPOErRpLtHWbm/giphy.gif" alt="" width="240" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Participar en proyectos de Software Libre/Open Source siempre es interesante, incluso si inicialmente solo ayudamos en la documentación para ir entendiendo el proyecto. Es también una acción muy relevante para &lt;strong&gt;apuntar la carrera profesional en una dirección concreta&lt;/strong&gt;. Por ejemplo encontrando un proyecto interesante que me guste y que una empresa que me interesa use, leyendo el código de mis proyectos favoritos y viendo cómo se siguen los estándares en proyectos grandes reales, esencial en mi humilde opinión.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dirigiéndome a una empresa
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Comprobar si tienen StackShare o encontrar una manera de conocer su stack y qué utilizan a bajo nivel.&lt;/li&gt;
&lt;li&gt;Comprobar su GitHub&lt;/li&gt;
&lt;li&gt;Comprobar a las personas relevantes que trabajan en esa empresa en LinkedIn, enviarles algún mensaje personal InMail incluso si no tienen posiciones abiertas, intentar sorprenderles con algo que hayas hecho.&lt;/li&gt;
&lt;li&gt;¡Usar las posibilidades que tenemos hoy en día en nuestro beneficio!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tests técnicos
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;No hay que tener miedo a estos tests, ya tenemos el no de entrada&lt;/li&gt;
&lt;li&gt;Abstraer funcionalidad (El Clean Code es un buen sitio para empezar)&lt;/li&gt;
&lt;li&gt;Tests automatizados, como el buen cocinero, tenemos que probar lo que cocinamos antes de servirlo&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  No mola
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A nadie le interesa saber lo mal que lo hacía la empresa en la que trabajaba anteriormente&lt;/li&gt;
&lt;li&gt;Si nos piden un video para conocernos antes de la entrevista, enfocarlo hacia mis habilidades con respecto a la oferta, no hacia nosotros. En un minuto de video podemos ahorrar muchas entrevistas, mejor preparar bien lo que podemos decir.&lt;/li&gt;
&lt;li&gt;Si no tenemos alguna habilidad que nos preguntan o no conocemos la respuesta a algo, intentar dar una respuesta alternativa con alguna habilidad parecida que tengamos o dejar muy claro que no sabemos la respuesta, mostrar capacidad de adaptación (Angular vs React, etc).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Cuantas más pistas demos a la empresa que me interesa sobre cómo trabajamos para llamar a su puerta mejor, es una primera impresión difícil de batir y es una buena manera de focalizar la futura entrevista hacia el contexto que nosotros hemos trabajado con nuestra marca personal.&lt;/p&gt;

&lt;p&gt;Si quieres trabajar en remoto y que una empresa confíe en tí, puedes empezar a mostrarlo en lo que haces ahora. Mostrar autonomía ser dueños de nuestra carrera, y poder elegir en vez de que nos elijan está en esta industria en nuestra mano. Ser un &lt;a href="https://signalvnoise.com/posts/1430-hire-managers-of-one"&gt;Manager Of One&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Estas son algunas de las cosas que he aprendido al haber estado en ambos lados (developer y recruiting) desde hace varios años, pero tu experiencia puede ser distinta a la mía, me encantaría que lo compartieses conmigo si tienes ocasión.&lt;/p&gt;

&lt;p&gt;¡Gracias!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/jpoDZOyEg38F4cFFMi/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/jpoDZOyEg38F4cFFMi/giphy.gif" alt="" width="480" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>recruiting</category>
      <category>junior</category>
      <category>spanish</category>
    </item>
    <item>
      <title>Why we ditched story points to be more value-oriented</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Wed, 11 Dec 2019 09:00:00 +0000</pubDate>
      <link>https://forem.com/wealize/why-we-ditched-story-points-to-be-more-feature-oriented-3i1i</link>
      <guid>https://forem.com/wealize/why-we-ditched-story-points-to-be-more-feature-oriented-3i1i</guid>
      <description>&lt;p&gt;At &lt;a href="https://theneonproject.org"&gt;TNP&lt;/a&gt; we worked using story points to estimate and control the amount of work everybody on the team was doing, but we decided to ditch it, here is why.&lt;/p&gt;

&lt;p&gt;We discovered several problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;People were stressed to finish their points, and they couldn’t focus on helping each other because they wanted to end their user stories. This issue was pushing individualism rather than quality and ship feature focus.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Having story points wasn’t pointing us to build faster or with more quality. User story points weren’t focusing the work on value but rather on risk, time, and complexity of the user story and features. 1-week sprints were making everything worse due to this fact when we finished features that weren’t good enough to put in production and were coming back to haunt us.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26hitt0thlwfoNRaE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26hitt0thlwfoNRaE/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We always like to iterate on processes to improve it and reduce friction at maximum, so everybody is comfortable working and focusing on delivering as much value as possible. With this idea, we decided to focus much more on delivery, following some rules.&lt;/p&gt;

&lt;p&gt;We have two-week sprints, and we organize teams by features, so everybody is on board to ship the feature and responsible for it. We don’t have departments, but feature teams with different roles. I haven’t invented this. It’s from &lt;a href="https://pragprog.com/book/rjnsd/the-nature-of-software-development"&gt;The Nature of Software Development book&lt;/a&gt; that &lt;a href="https://twitter.com/stanete"&gt;@stanete&lt;/a&gt; recommended some time ago. Every user story or feature has a team behind, design, product, development, and everybody is needed to accomplish it.&lt;/p&gt;

&lt;p&gt;We had to improve user story definition, make them more shippable and self-contained so we could deploy each of them with value for the client. That’s why we decided to be much more product-oriented. Make those &lt;em&gt;minimum viable features&lt;/em&gt; to adjust the value and time consumption working on them. This idea is probably the most difficult to achieve. Still, we think it is better to work in this direction rather than trying to estimate better, which won’t focus on deliverability but internal needs.&lt;/p&gt;

&lt;p&gt;This new way of working makes it more natural to have other advantages for the team. For example, when someone finished their stories early, he/she has to help the rest of the team on the features to complete for this sprint so we can ship as a team. We have time every week to learn in the process because we’re not stressed, and the time is much less tight. Improve accomplishment managing scope rather than improving estimates. We plan to do as much as in the last iteration to do good work at a consistent pace.&lt;/p&gt;

&lt;p&gt;In the case of engineering tasks and reducing technical debt, we follow the rule ‘leave the campground better than you found it.’ I have adopted that rule for years since I read &lt;a href="https://www.amazon.es/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882"&gt;Clean Code&lt;/a&gt;, but all the team must stay in tune, so every time we do a feature, we can clean up the area where we are going to work. We’re exhaustive on testing and good quality code to avoid technical debt. We also try to move the QA phase of the feature as soon as possible and not only when it’s done. Once we ship, the feature shouldn’t come back with defects in it; otherwise, It disrupts our development pace.&lt;/p&gt;

&lt;p&gt;We haven’t invented this way of working. Some of the tips are from the Influence of the &lt;strong&gt;Nature of Software Development and Clean Code&lt;/strong&gt; , among other books. We’re always iterating to improve our processes and learning new things so that these changes will vary in the future.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/6brH8dM3zeMyA/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/6brH8dM3zeMyA/giphy.gif" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover Photo by Franck V. on Unsplash&lt;/em&gt;&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>feature</category>
      <category>delivery</category>
      <category>product</category>
    </item>
    <item>
      <title>Get release tag from GitHub Actions to debug on Heroku</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Thu, 28 Nov 2019 09:00:00 +0000</pubDate>
      <link>https://forem.com/wealize/get-release-tag-from-github-actions-to-debug-on-heroku-3583</link>
      <guid>https://forem.com/wealize/get-release-tag-from-github-actions-to-debug-on-heroku-3583</guid>
      <description>&lt;p&gt;In TNP we’ve moved everything to GitHub Actions and we’re very happy about it. :-)&lt;/p&gt;

&lt;p&gt;But… this article is not about how happy we are using it but a small tip on how we could simplify every day debugging with some simple improvements.&lt;/p&gt;

&lt;p&gt;As a good metric oriented company, We measure and monitor everything we believe relevant, this is a solution to control which release we have in production and being able to monitor its breaking changes in a simple way.&lt;/p&gt;

&lt;p&gt;We decided to add the git release tag to our deploy and our app footers, with the following steps.&lt;/p&gt;

&lt;p&gt;First, We push to production only when a git tag (a release) is created on GitHub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;

  &lt;span class="s"&gt;deploy_production&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;

    &lt;span class="s"&gt;if&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;success() &amp;amp;&amp;amp; contains(github.ref, 'tags')&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We deploy to Heroku where is super easy to set a config variable via API, so we decided to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Get the release tag from the current release&lt;/li&gt;
&lt;li&gt;Update a &lt;code&gt;RELEASE_VERSION&lt;/code&gt; variable on Heroku every time a new deploy is successful.&lt;/li&gt;
&lt;li&gt;Profit!
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Push to Heroku&lt;/span&gt;
   &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git push -f https://heroku:${{ secrets.HEROKU_API_TOKEN }}@git.heroku.com/${{ secrets.HEROKU_APP_PRODUCTION }}.git origin/master:master&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update RELEASE_VERSION on Heroku production&lt;/span&gt;
   &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;success()&lt;/span&gt;
   &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;curl -n -X PATCH https://api.heroku.com/apps/${{ secrets.HEROKU_APP_PRODUCTION }}/config-vars \&lt;/span&gt;
    &lt;span class="s"&gt;-d '{&lt;/span&gt;
      &lt;span class="s"&gt;"RELEASE_VERSION”: "${{ github.ref }}",&lt;/span&gt;
    &lt;span class="s"&gt;}’ \&lt;/span&gt;
    &lt;span class="s"&gt;-H "Authorization: Bearer ${{ secrets.GITHUB_API_TOKEN }}"&lt;/span&gt;
    &lt;span class="s"&gt;-H "Content-Type: application/json" \&lt;/span&gt;
    &lt;span class="s"&gt;-H "Accept: application/vnd.heroku+json; version=3"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to set two variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;HEROKU_API_TOKEN&lt;/code&gt;: Your personal token, you can get it from your &lt;a href="https://dashboard.heroku.com/account"&gt;account settings&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;HEROKU_APP_PRODUCTION&lt;/code&gt;: Your production app name on Heroku, we don’t hardcode it, so it’s easier to share these recipes in other projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s It! You’ll have something like this on your Heroku app if all goes well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UKiDaAuu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/488556/69890303-37c27600-12f5-11ea-9280-6a89fa3b74c4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UKiDaAuu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://user-images.githubusercontent.com/488556/69890303-37c27600-12f5-11ea-9280-6a89fa3b74c4.png" alt="Screenshot 2019-11-29 at 22 10 38" width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover Image Garett Mizunaka - Unsplash&lt;/em&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>actions</category>
      <category>cicd</category>
      <category>heroku</category>
    </item>
    <item>
      <title>Automatize your new developer’s team onboarding with this simple app (in Python)</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Sun, 23 Jun 2019 09:00:00 +0000</pubDate>
      <link>https://forem.com/wealize/automatize-your-new-developer-s-team-onboarding-with-this-simple-app-in-python-22pg</link>
      <guid>https://forem.com/wealize/automatize-your-new-developer-s-team-onboarding-with-this-simple-app-in-python-22pg</guid>
      <description>&lt;p&gt;When a new developer joins our team, everybody wants to give them the best possible experience 🙌.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/FQyQEYd0KlYQ/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/FQyQEYd0KlYQ/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We’ve created a simple command line app in Python that with minimum configuration helps the new developer, in a geeky way, set up his/her environment and checks if everything works! It also gives information about which services would they have access to so they can check and don’t need to go somewhere else for that info.&lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://click.palletsprojects.com/en/7.x/" rel="noopener noreferrer"&gt;Click&lt;/a&gt;, the library to create Command line interfaces in Python, and YAML for the configuration. The config has a specific structure moreover, we can configure the file path so someone could reuse the project for their own company 🤓.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TheNeonProject/onboarding" rel="noopener noreferrer"&gt;The documentation is in the README&lt;/a&gt;. You can set the company information in the config, as &lt;a href="https://github.com/TheNeonProject/onboarding/blob/master/config.yml" rel="noopener noreferrer"&gt;in our own that you could use as an example&lt;/a&gt;. To use your config file, you can set &lt;code&gt;ONBOARDING_FILE_PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can install it with &lt;a href="https://github.com/pypa/pipenv" rel="noopener noreferrer"&gt;pipenv&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;pipenv
pipenv &lt;span class="nt"&gt;--python&lt;/span&gt; 3.7
pipenv &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once this command finishes, we can run it using &lt;code&gt;pipenv&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ONBOARDING_FILE_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;config.yml
pipenv run python cli.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/TheNeonProject/onboarding/blob/master/.vscode/launch.json" rel="noopener noreferrer"&gt;It has the configuration to launch from VS Code Debug tab too&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can see here the output of the app with my company configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F488556%2F59706185-3a765680-9200-11e9-90ce-490c377e7016.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F488556%2F59706185-3a765680-9200-11e9-90ce-490c377e7016.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F488556%2F59706184-3a765680-9200-11e9-9a29-a10e7fe8fff1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fuser-images.githubusercontent.com%2F488556%2F59706184-3a765680-9200-11e9-9a29-a10e7fe8fff1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/TheNeonProject/onboarding" rel="noopener noreferrer"&gt;The project is open source and can you can clone it from GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Maybe if we have time, we’ll create a Python package and add more functionality 🎸, but for now, it does the trick. :-)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cover image by Photo by Harley-Davidson on Unsplash&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>management</category>
      <category>onboarding</category>
    </item>
    <item>
      <title>The Journey to control Code Quality</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Wed, 05 Jun 2019 22:21:00 +0000</pubDate>
      <link>https://forem.com/wealize/the-journey-to-control-code-quality-4njl</link>
      <guid>https://forem.com/wealize/the-journey-to-control-code-quality-4njl</guid>
      <description>&lt;p&gt;Coding, programming, developing, name your action! Such a funny and exciting amusement, sometimes going wrong under stress or when lacking experience in a certain technology.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Challenge
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xTkcERvSGMZOpp9RkI/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xTkcERvSGMZOpp9RkI/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We sometimes need to write code we’re not proud of, but nowadays we have mechanisms to quantify that and improve its quality. Like boy scouts, we can go back and clean the camp, make more tests because we didn’t have enough coverage and we could be not catching all the possible bugs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/pFwRzOLfuGHok/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/pFwRzOLfuGHok/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When I go back and read my code from some time ago, I’m ashamed, and that’s a good thing, It means we’re growing. Otherwise, we wouldn’t notice.&lt;/p&gt;

&lt;p&gt;I’ve always been in the improving code quality path, I know projects and startups need to achieve their goals, otherwise, we all could lose our jobs, but that’s why it’s so important to have proper processes and a good CI/CD, control code quality, and measure legacy code so it doesn’t grow too much.&lt;/p&gt;

&lt;p&gt;I’ve been a testing advocate for years now. I know what we should test and what is more challenging to test, why should we refactor if our tests are too complex because we have an architecture problem, what parts are more likely to be problematic. Still, there is usually doubt, risk and terror.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Qw4X3FN8Elnz2ew3UFa/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Qw4X3FN8Elnz2ew3UFa/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, when you’re in a small agency like mine, you need to have metrics, you need to rely on excellent services, so you save all the time possible to do what it gives value to the company. We need to improve the process every time (otherwise what’s the fun in doing everything always the same way right? :-)).&lt;/p&gt;

&lt;h1&gt;
  
  
  The Journey
&lt;/h1&gt;

&lt;p&gt;Our journey for a better code starts with reviews, we defined the user story and estimated the cost of development (more on this on the following article), a member of the team got to it, implemented it and created a PR on GitHub.&lt;/p&gt;

&lt;p&gt;The first step, in this case, assures two checks are passing within the PR:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gitlab CI&lt;/strong&gt; would run the tests and tell us if they passed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codacy&lt;/strong&gt; tells us if there were significant regressions in terms of code complexity, code duplication, standards, and code coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the checks pass at least a developer in the team reviews the PR code for clarity, good patterns, functionality. If everything goes well, the code gets merged to the release branch and, when the sprint ends, to master. We can never remove the human interaction since code patterns, architecture and naming are so dependant on the domain and context of the application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6xq9hl5qij6n7kmbcqce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6xq9hl5qij6n7kmbcqce.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codacy.com" rel="noopener noreferrer"&gt;Codacy&lt;/a&gt; brings us more functionality than other contenders, such as &lt;a href="https://danger.systems/" rel="noopener noreferrer"&gt;Danger&lt;/a&gt; or &lt;a href="https://codeclimate.com/" rel="noopener noreferrer"&gt;Code Climate&lt;/a&gt;, but if you don’t like it, you might check it out those. We chose Codacy over the others because it gave us better progress feedback, and they have excellent code coverage integration, much easier to set up than Code Climate (for example). It gave us more than Danger since Danger is usually more used as linter but doesn’t get anything regarding code coverage.&lt;/p&gt;

&lt;p&gt;When we started using Codacy, something great happened, the Pull Requests were more alive since everybody was trying to minimize the technical debt they were adding, so Codacy gamified our Pull Requests too. :-)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwpzpenl2rrgyph2xk4my.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwpzpenl2rrgyph2xk4my.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Codacy integrates with many languages, we usually use Python Pylint, Bandit, Prospector, and ESLint for Node. Codacy would read these libraries config in your repositories and use that configuration if it exists. Otherwise, you can check the configuration items you want from a particular tool right from their project settings view.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F66nfdt7wqxlkmy2hq481.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F66nfdt7wqxlkmy2hq481.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At that point, our CI gets triggered (because we merge to master) and if the tests pass the code is automatically deployed to our staging environment, usually Heroku, but also AWS/Kubernetes.&lt;/p&gt;

&lt;p&gt;When we want to deploy to production, we create a new tag like &lt;strong&gt;vYYYY.MM.DD&lt;/strong&gt; and the CI/CD triggers the deploy to production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fjavaguirre.me%2Fassets%2Fimages%2Fgitlab-ci1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/http%3A%2F%2Fjavaguirre.me%2Fassets%2Fimages%2Fgitlab-ci1.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  The Destiny
&lt;/h1&gt;

&lt;p&gt;When the code reaches production, we have two services giving us input so we know if something is wrong or an alert is triggered.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://sentry.io" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt; has been my favorite for years in terms of controlling errors in production, it’s straightforward to use, to tag, to separate between different environments (backend, frontend, mobile) and it works so well!&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://newrelic.com/" rel="noopener noreferrer"&gt;New Relic&lt;/a&gt; is mighty, and we use it to detect bottlenecks and performance problems when they occur (or before it is too late if you configure your alerts well!). It’s so nice to be able to monitor your queries and see how are they behaving to be able to prevent a problem in the future, New Relic is excellent for that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/cI5CL3l9kZ62w0Kh3c/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/cI5CL3l9kZ62w0Kh3c/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What are your favourites? What are your recommendations? Let me know!&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>cicd</category>
      <category>codacy</category>
    </item>
    <item>
      <title>Debug Python and Django easily from Visual Studio Code</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Wed, 22 May 2019 22:21:00 +0000</pubDate>
      <link>https://forem.com/wealize/debug-python-and-django-easily-from-visual-studio-code-4dfk</link>
      <guid>https://forem.com/wealize/debug-python-and-django-easily-from-visual-studio-code-4dfk</guid>
      <description>&lt;p&gt;Debugging code, sometimes painful, sometimes funny, but always an exciting task.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fheqpunsveb24zdu61swv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fheqpunsveb24zdu61swv.gif" width="250" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we don’t use the right tools, It’s where the developer can waste more time. Making debugging easy for developers has been sometimes a problem for technology, but fortunately, in Python, there have been good debug options right from the start.&lt;/p&gt;

&lt;p&gt;Visual Studio Code has a very powerful and configurable tab where you can define the desired configuration for your project. You can have all the configurations you want! (for testing, debugging, running a specific process…)&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;From VS Code, we can easily debug Python code locally but also when running inside of a Docker container using ptvsd. I’ll tell you how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Print
&lt;/h2&gt;

&lt;p&gt;We all have printed code at some point of our career, but the path to becoming a better developer goes beyond that, it’s essential to spend time researching until we find better tools for the task.&lt;/p&gt;

&lt;p&gt;Printing has never been cool, but before learning the proper debugging tools, it has always been that quick and dirty option to check variable output.&lt;/p&gt;

&lt;h2&gt;
  
  
  PDB
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;PDB&lt;/strong&gt; and &lt;strong&gt;pudb&lt;/strong&gt; are great tools! I still use them sometimes when I want to debug something tricky, but for debugging speed purposes I find much more convenient using VS Code Debug tab, where I can see all the context on a specific line of code.&lt;/p&gt;

&lt;p&gt;Before that, I used to have a snippet for &lt;code&gt;pdb&lt;/code&gt;, and that would extend to &lt;code&gt;import pdb; pdb.set_trace()&lt;/code&gt; so I could stop the execution at a specific line of code. Then with &lt;code&gt;(n)ext&lt;/code&gt;, &lt;code&gt;(c)ontinue&lt;/code&gt;, &lt;code&gt;(q)uit&lt;/code&gt;… I could control the execution line by line and &lt;code&gt;step into&lt;/code&gt; a specific function or method (more on &lt;a href="https://docs.python.org/3/library/pdb.html"&gt;pdb&lt;/a&gt; and &lt;a href="https://pypi.org/project/pudb/"&gt;pudb&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  VS Code
&lt;/h2&gt;

&lt;p&gt;After a while using VS Code I started getting deep into different user and workspace configurations on Django and Node/React, this article gives an example on how we could configure a Django project to use the VS Code debugging tab.&lt;/p&gt;

&lt;p&gt;Starting services having installed a Django project locally is easy, we could just use runserver. We’d click the Debug tab, select &lt;code&gt;Add configuration...&lt;/code&gt; in the selector and follow the wizard selecting &lt;code&gt;Django: runserver&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feonsw6lemtleeis76ofg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feonsw6lemtleeis76ofg.png" width="800" height="701"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The configuration would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Django: Runserver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/manage.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"runserver"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--noreload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"--nothreading"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"django"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use &lt;code&gt;pipenv&lt;/code&gt;, &lt;code&gt;virtualenv&lt;/code&gt; or have selected the &lt;code&gt;pythonPath&lt;/code&gt; on your workspace configuration (&lt;code&gt;Command-,&lt;/code&gt; on Mac), VS Code knows how to run the command automatically. We could have a command for testing too, having an &lt;code&gt;envvar&lt;/code&gt; to select another &lt;code&gt;DJANGO_SETTINGS_MODULE&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Django: Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/manage.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"env"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"DJANGO_SETTINGS_MODULE"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myproject.settings.test"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"test"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"django"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’d click play and have our tests passed. :-)&lt;/p&gt;

&lt;h2&gt;
  
  
  VS Code debug in Docker
&lt;/h2&gt;

&lt;p&gt;Debugging inside a Docker container is a bit trickier, we need to open a &lt;code&gt;socket&lt;/code&gt; so we can debug from VS Code, let’s see how.&lt;/p&gt;

&lt;p&gt;Our Django Dockerfile looks something like this if we use &lt;code&gt;pipenv&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.7&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /code

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /code&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;pipenv
&lt;span class="k"&gt;ADD&lt;/span&gt;&lt;span class="s"&gt; Pipfile /code/&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pipenv &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--dev&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /code/&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could have a &lt;code&gt;docker-compose.yml&lt;/code&gt; file to manage dependencies easier, such as &lt;code&gt;postgres&lt;/code&gt;, &lt;code&gt;redis&lt;/code&gt;, or just the ports opened for the host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.7'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;

  &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydjangoproject&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pipenv run manage.py runserver 0.0.0.0:8000&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DJANGO_DEBUG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myproject.settings.local&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/code&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8000:8000&lt;/span&gt; &lt;span class="c1"&gt;# Serving Django&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8888:8888&lt;/span&gt; &lt;span class="c1"&gt;# debugging service (ptvsd)&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;

  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we open the &lt;code&gt;8000&lt;/code&gt; for Django &lt;code&gt;runserver&lt;/code&gt; and the &lt;code&gt;8888&lt;/code&gt; so VS Code can connect via the Debug tab to Django.&lt;/p&gt;

&lt;p&gt;To be able to do this, Microsoft created a library, &lt;a href="https://github.com/microsoft/ptvsd"&gt;ptvsd&lt;/a&gt; &lt;strong&gt;the Python tools for the Visual Studio debugger&lt;/strong&gt;. This library runs within our Python code and opens a socket we can connect to debug the application. In Django, we can put it on the &lt;code&gt;wsgi.py&lt;/code&gt; file and It will only run if &lt;code&gt;settings.DEBUG&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.core.wsgi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_wsgi_application&lt;/span&gt;

&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setdefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DJANGO_SETTINGS_MODULE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;myproject.settings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;DJANGO_DEBUG&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;# You can use django.conf settings.DEBUG
&lt;/span&gt;    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ptvsd&lt;/span&gt;
    &lt;span class="n"&gt;ptvsd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable_attach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8888&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;ptvsd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait_for_attach&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;# We can remove this line it gives you trouble,
&lt;/span&gt;                             &lt;span class="c1"&gt;# but it's good to know if the debugger started or not
&lt;/span&gt;                             &lt;span class="c1"&gt;# blocking the execution for a while :-)
&lt;/span&gt;
&lt;span class="n"&gt;application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_wsgi_application&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We open the socket to the outside world &lt;code&gt;0.0.0.0&lt;/code&gt; in the port &lt;code&gt;8888&lt;/code&gt; so we can connect from the host, our machine.&lt;/p&gt;

&lt;p&gt;We execute our &lt;code&gt;docker-compose&lt;/code&gt; script, in my case &lt;code&gt;docker-compose up backend&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In VS Code the configuration would be pretty straight forward, we add the &lt;code&gt;port&lt;/code&gt; where ptvsd opened the socket, we tell VS Code, our &lt;code&gt;localRoot&lt;/code&gt; is the current project and the &lt;code&gt;remoteRoot&lt;/code&gt; which is my &lt;code&gt;/code&lt;/code&gt; path, defined on my &lt;code&gt;Dockerfile&lt;/code&gt; for this project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Remote Django App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"python"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"attach"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pathMappings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"localRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"remoteRoot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/code"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8888&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now It’s when the magic happens! You should be able to do something like this. :-)&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/oyKkQzvUVMU"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Do you know more tricks debugging on VS Code? Let me know in the comments!&lt;/p&gt;

</description>
      <category>python</category>
      <category>vscode</category>
      <category>django</category>
    </item>
    <item>
      <title>Common Git problems and easy incremental solutions for all the family</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Wed, 22 May 2019 21:07:59 +0000</pubDate>
      <link>https://forem.com/wealize/common-git-problems-and-easy-incremental-solutions-for-all-the-family-10gd</link>
      <guid>https://forem.com/wealize/common-git-problems-and-easy-incremental-solutions-for-all-the-family-10gd</guid>
      <description>&lt;p&gt;Git is a gentle beast, but beasts are wild, and they require taming, here are some tips to resolve 99% of git problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3oEduIpnblLzPwzJPG/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3oEduIpnblLzPwzJPG/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Working with developers of different experience levels made me realize we should have a simple suitable method to resolve all possible issues when working on a git project, that's why I wrote this tutorial in the first place.&lt;/p&gt;

&lt;p&gt;At my company, we follow a small variation of &lt;a href="https://es.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow" rel="noopener noreferrer"&gt;git flow&lt;/a&gt;, where there are no &lt;strong&gt;develop&lt;/strong&gt; branch, but a &lt;strong&gt;release&lt;/strong&gt; one&lt;br&gt;
that gets merged every sprint with &lt;strong&gt;master&lt;/strong&gt; and gets recreated for the next sprint until we merge again, deploying automatically to production.&lt;/p&gt;

&lt;p&gt;We did this variation because we found out that keeping the &lt;strong&gt;develop&lt;/strong&gt; branch neat and clean when there are different levels of git knowledge in the company is challenging.&lt;/p&gt;

&lt;p&gt;We use &lt;strong&gt;git fetch&lt;/strong&gt; to update our git database locally, so we have the latest changes. In case of doubt, we always rebase and create branches from &lt;strong&gt;origin&lt;/strong&gt;, never from a local branch because we might mess up.&lt;/p&gt;

&lt;p&gt;When developing a feature, we always use &lt;strong&gt;rebase&lt;/strong&gt; to update our current feature from &lt;strong&gt;release&lt;/strong&gt;. We squash the &lt;strong&gt;feature&lt;/strong&gt; branches into one commit, so it's easy to rollback a feature once it is reviewed and ready to merge.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Being on the feature/my-tasty-feature branch&lt;/span&gt;

git fetch origin
git rebase origin/release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating a feature branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Being on master or release or any other branch different from the one created&lt;/span&gt;

git fetch origin
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/my-tasty-feature origin/release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  First problem and solution
&lt;/h2&gt;

&lt;p&gt;We need to update our code with &lt;strong&gt;release&lt;/strong&gt; because we don't have the latest changes. In our feature branch we can do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Being on the feature/my-tasty-feature branch&lt;/span&gt;

git fetch origin
git rebase origin/release
git push &lt;span class="nt"&gt;-f&lt;/span&gt; feature/my-tasty-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-f&lt;/code&gt; can only be used on an unmerged personal branch. It means &lt;em&gt;force&lt;/em&gt; and it rewrites the git history, so we need to be very careful when using it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Second problem and solution
&lt;/h2&gt;

&lt;p&gt;We have to rebase from &lt;strong&gt;release&lt;/strong&gt;, we have many commits, and we need to solve several conflicts on different painfully commits, we need to make our branch changes into one!&lt;/p&gt;

&lt;p&gt;First, we need to know how many commits do we want to add to &lt;strong&gt;release&lt;/strong&gt; and squash them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Being on the feature/my-tasty-feature branch&lt;/span&gt;

git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; HEAD~5 &lt;span class="c"&gt;# where five is the number of commits&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We replace all the first lines &lt;strong&gt;pick&lt;/strong&gt; for &lt;strong&gt;squash&lt;/strong&gt; except in the first line and save.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh5xfptmpnqrcsacl3ujn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh5xfptmpnqrcsacl3ujn.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Farxr6ftdute5fun5va7w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Farxr6ftdute5fun5va7w.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can change the commit name and put something relevant, save the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fi7qlkxyvbuhqv4co9k0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fi7qlkxyvbuhqv4co9k0c.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99kcy65673fnm9jhvkkr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99kcy65673fnm9jhvkkr.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1h6sjduvwot1x6gtsz6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1h6sjduvwot1x6gtsz6k.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we need to fix the conflict:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Being on the feature/my-tasty-feature branch&lt;/span&gt;

git rebase origin/release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We fix the conflicts on our favorite editor and add the files, then&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Being on the feature/my-tasty-feature branch&lt;/span&gt;

git rebase &lt;span class="nt"&gt;--continue&lt;/span&gt;
git push &lt;span class="nt"&gt;-f&lt;/span&gt; feature/my-tasty-feature
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Third problem and solution
&lt;/h2&gt;

&lt;p&gt;In our GitHub pull request we have commits that don't belong to our branch, but are from &lt;strong&gt;release&lt;/strong&gt;, this might happen for two reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Because we didn't do the &lt;em&gt;first solution&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Because we updated the &lt;strong&gt;master&lt;/strong&gt; branch and some commit hashes have changed (This should seldom happen).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://es.atlassian.com/git/tutorials/rewriting-history/git-rebase" rel="noopener noreferrer"&gt;Check the link if you want to know more about how &lt;code&gt;rebase&lt;/code&gt; works&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this case, the best approach (or most straightforward) is usually to rebuild our branch. First, we need to know how many commits do we want to add to &lt;strong&gt;release&lt;/strong&gt; and squash them, so we'll do the &lt;em&gt;second solution&lt;/em&gt; entirely.&lt;/p&gt;

&lt;p&gt;After doing the second solution, we'll do the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# We are on the feature/my-tasty-feature branch&lt;/span&gt;

git fetch origin

git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/my-backup-branch origin/feature/my-tasty-branch

&lt;span class="c"&gt;# We delete the branch we're going to rebuild locally&lt;/span&gt;

&lt;span class="c"&gt;# We are on feature/my-backup-branch&lt;/span&gt;
git branch &lt;span class="nt"&gt;-D&lt;/span&gt; feature/my-tasty-branch
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; feature/my-tasty-branch origin/release

git log feature/my-backup-branch

&lt;span class="c"&gt;# We are on feature/my-tasty-branch&lt;/span&gt;
&lt;span class="c"&gt;# We copy the last commit hash (see screenshot below)&lt;/span&gt;
git cherry-pick the-hash-we-have-copied
git push &lt;span class="nt"&gt;-f&lt;/span&gt; origin/feature/my-tasty-branch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5swzgk561fnx3941dpm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5swzgk561fnx3941dpm8.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Done!&lt;/p&gt;

&lt;p&gt;These are my tips for people starting on my team when they have problems with Git, what do you think? Would you change anything? Any recommendations?&lt;/p&gt;

</description>
      <category>git</category>
    </item>
    <item>
      <title>CI/CD on a Hyperledger Fabric project</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Mon, 20 May 2019 18:43:17 +0000</pubDate>
      <link>https://forem.com/wealize/ci-cd-on-a-hyperledger-fabric-project-83b</link>
      <guid>https://forem.com/wealize/ci-cd-on-a-hyperledger-fabric-project-83b</guid>
      <description>&lt;p&gt;Today we bring you the second post of this series of technical articles regarding development with Hyperledger Fabric.&lt;/p&gt;

&lt;p&gt;Last time we &lt;a href="https://dev.to/javaguirre/testing-chaincode-on-hyperledger-fabric-2j8k"&gt;talked about how we test our chaincode&lt;/a&gt;,&lt;br&gt;
today we go one step further and we’ll show you how we deploy the code automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/26DNdV3b6dqn1jzR6/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/26DNdV3b6dqn1jzR6/giphy.gif" alt="" width="470" height="264"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CI/CD&lt;/strong&gt; is the combined practice of automating the testing of our application and the deployment of the application to our servers.&lt;/p&gt;

&lt;p&gt;Our workflow integrates different platforms in our pipeline, Github, Gitlab CI and IBM Blockchain. We store the code in Github, when we push code to Github it automatically goes to Gitlab CI where the automated tests are executed. If everything goes well we deploy the code to IBM automatically.&lt;/p&gt;
&lt;h1&gt;
  
  
  Continuous Integration
&lt;/h1&gt;

&lt;p&gt;Continuous Integration is a practice that requires developers to &lt;strong&gt;integrate&lt;/strong&gt; code into a shared repository several times a day. Every time the code is pushed to the code repository, the automated tests are executed.&lt;/p&gt;

&lt;p&gt;There are many cool CI services and we’ve used several of them, right now we’re happy with Gitlab CI, very easy to configure and full of possibilities!&lt;/p&gt;

&lt;p&gt;There are two phases on our CI/CD process: the testing and the deploy phase. You can have several phases in parallel, in the test phase we run three processes, backend, frontend, and chaincode testing. When the tests pass and if the rules are met, the application and chaincode are &lt;em&gt;deployed&lt;/em&gt;. :-)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/KsCtl2h2RZKso/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/KsCtl2h2RZKso/giphy.gif" alt="" width="361" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we’re gonna show you the configuration for the chaincode only since the rest of the application is well documented everywhere (we use industry standards such as Django, React, etc…).&lt;/p&gt;

&lt;p&gt;In the test phase we run the chaincode tests with this configuration, the steps are documented in the code snippet:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h1&gt;
  
  
  Continuous Delivery
&lt;/h1&gt;

&lt;p&gt;Every change that passes the automated tests is deployed to production automatically, so when the tests pass it’s time to deploy!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/CDZwopbecAbIc/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/CDZwopbecAbIc/giphy.gif" alt="" width="706" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This stage is executed only in two specific cases, for the &lt;strong&gt;staging&lt;/strong&gt; and the &lt;strong&gt;production&lt;/strong&gt; environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Staging&lt;/strong&gt;: When we push the changes to &lt;strong&gt;master&lt;/strong&gt; in Git&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production&lt;/strong&gt;: When we push the changes with a Git &lt;strong&gt;tag&lt;/strong&gt;. We use the following formats for the tags &lt;em&gt;vYYYY.MM.DD&lt;/em&gt; (Year.Month.Day)&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Each deploy consists of two API calls. The first one is used to &lt;strong&gt;install the chaincode in the platform&lt;/strong&gt;, the second one to &lt;strong&gt;instantiate the chaincode in one of our channels&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can read the &lt;a href="https://blockchain-starter.eu-gb.bluemix.net/api-docs/#/Channels/instantiateChaincode"&gt;IBM Blockchain API documentation&lt;/a&gt; to know what can you send on these API calls.&lt;/p&gt;

&lt;p&gt;The variables used within Gitlab CI are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NETWORK_ID&lt;/strong&gt;: network_id in IBM Network credentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NETWORK_KEY&lt;/strong&gt;: key in IBM Network credentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NETWORK_PASS&lt;/strong&gt;: secret in IBM Network credentials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CHANNEL_{ENVIRONMENT}_ID&lt;/strong&gt;: the channel is the name we added when we created the channel for this project (&lt;em&gt;defaultchannel&lt;/em&gt; by default on IBM Blockchain)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://gist.github.com/javaguirre/24130c063131f7c5a0bee1022b4ebdac"&gt;See the entire example recipe to CI/CD Hyperledger Fabric on IBM Blockchain&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Enter IBM Blockchain
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VN96sW9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/u2e5cnma6keaophto8d9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VN96sW9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/u2e5cnma6keaophto8d9.png" alt="" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;IBM Blockchain&lt;/strong&gt; platform is, by far, the easiest way we used to build a Hyperledger Fabric network, it has also a nice API to interact with it remotely, it saves a lot of time and pain not needing to administer any of the typical components within a Fabric network. There are only some details we need to take into account when using it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When we deploy several smart contracts with the same name it might be difficult to know which is the last one deployed, there is no chaincode grouping by name.&lt;/li&gt;
&lt;li&gt;There is no way of archiving old chaincode release, so we end up with many chaincode versions in the chaincode list.&lt;/li&gt;
&lt;li&gt;There is no way of telling IBM Blockchain that my smart contract, built in Go, has an external dependency.&lt;/li&gt;
&lt;li&gt;Logging is not integrated in the platform, it opens a Kibana dashboard for us to see the logs (I’m not sure if this is good or bad, but the experience is weird).&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Once CI/CD is well configured, creating and instantiating chaincode on IBM Blockchain is a breeze, but there are some caveats we need to overcome to get the most of their platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/KINAUcarXNxWE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/KINAUcarXNxWE/giphy.gif" alt="" width="500" height="333"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post was written on my &lt;a href="https://javaguirre.me/2019/02/25/cicd-hyperledger-fabric-chaincode-golang"&gt;blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>hyperledger</category>
      <category>devops</category>
    </item>
    <item>
      <title>Testing chaincode on Hyperledger Fabric</title>
      <dc:creator>Javier Aguirre</dc:creator>
      <pubDate>Sun, 19 May 2019 22:10:20 +0000</pubDate>
      <link>https://forem.com/wealize/testing-chaincode-on-hyperledger-fabric-2j8k</link>
      <guid>https://forem.com/wealize/testing-chaincode-on-hyperledger-fabric-2j8k</guid>
      <description>&lt;p&gt;&lt;a href="https://www.hyperledger.org/"&gt;Hyperledger&lt;/a&gt; is the Blockchain family of tools and frameworks for permissioned networks. &lt;a href="https://theneonproject.org"&gt;We've&lt;/a&gt; been working with solutions built with &lt;a href="https://www.hyperledger.org/projects/fabric"&gt;Hyperledger Fabric&lt;/a&gt; for a while now.&lt;/p&gt;

&lt;p&gt;Hyperledger Fabric is a complex system to deploy and it’s important to be careful when we configure certificates, open ports or assign roles, among other things. Luckily there are some good documentation articles from Hyperledger you could read to extend your knowledge if you are interested, such as &lt;a href="https://hyperledger-fabric.readthedocs.io/en/latest/build_network.html"&gt;how to build your first network&lt;/a&gt; or &lt;a href="https://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html"&gt;writing your first application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our workflow integrates different platforms in our pipeline: It starts on Github, goes to Gitlab CI and finally deploys the smart contract on the IBM Blockchain platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8cnkWZv9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/kyselcfls5np9wnnms1w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8cnkWZv9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/kyselcfls5np9wnnms1w.png" alt="" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Today we want to talk about the first part that makes our development faster, the unit, integration and acceptance tests for the chaincode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test all the things!
&lt;/h2&gt;

&lt;p&gt;We have automated testing at our core. &lt;a href="https://en.wikipedia.org/wiki/CI/CD"&gt;We apply Continuous Integration and Continuous Delivery&lt;/a&gt; in all our projects,&lt;br&gt;
so it made sense for us to create a more robust test suite for our chaincode.&lt;/p&gt;

&lt;p&gt;We decided to go with Go, static typing, Go structs and the &lt;a href="https://github.com/hyperledger/fabric-test"&gt;examples in the Hyperledger Fabric official repositories&lt;/a&gt; made testing easy and straightforward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/LFmxDLUTQH7dS/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LFmxDLUTQH7dS/giphy.gif" alt="" width="500" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make Hyperledger Fabric chaincode easier to test, the developers have created a &lt;a href="https://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim#NewMockStub"&gt;MockStub&lt;/a&gt; struct. A mock is a service simulating functionality so you don’t call the real one while testing. For example, if we use a service to send SMS, we don’t want our tests to send SMS every time we run them, that’s why we usually use a mock, to simulate we call the method and its response. There are still several commands that &lt;a href="https://github.com/hyperledger/fabric/blob/release-1.4/core/chaincode/shim/mockstub.go#L282-L293"&gt;aren’t implemented in the mock needed for some of the MockStub&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Run the tests
&lt;/h2&gt;

&lt;p&gt;To run the tests locally, we use a &lt;em&gt;Dockerfile&lt;/em&gt; that builds our environment. The &lt;strong&gt;Dockerfile&lt;/strong&gt; would be something like this:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We’re using &lt;strong&gt;Go v1.10&lt;/strong&gt; and copying our project code to &lt;strong&gt;/go/src/app&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We need to install the dependencies, we’ll use &lt;a href="https://github.com/hyperledger/fabric-sdk-go"&gt;hyperledger/fabric-sdk-go&lt;/a&gt;, &lt;a href="https://godoc.org/github.com/pgpst/pgpst/internal/github.com/stretchr/testify/assert"&gt;testify/assert&lt;/a&gt; to have a nice way of asserting in our tests and optionally if we do acceptance tests, &lt;a href="https://github.com/DATA-DOG/godog"&gt;cmd/godog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We’ll need &lt;strong&gt;libltdl-dev&lt;/strong&gt; and install in the Fabric library manually in the &lt;strong&gt;$GOPATH&lt;/strong&gt;, it didn’t work for us at the time, but this might be easier with the new version of Fabric.&lt;/p&gt;

&lt;p&gt;We define the path where our chaincode lives (&lt;em&gt;$GOPATH/src/gitlab.com/TheNeonProject/mychaincode&lt;/em&gt;) and run the tests with go test -v ..&lt;/p&gt;

&lt;p&gt;To run this locally we use two commands, one to build the Docker container, and another one to run the tests.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We’ll get a response like this if everything went nicely.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sY3Bh4A1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/4e4t4d7fwyov2kzjrwai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sY3Bh4A1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://thepracticaldev.s3.amazonaws.com/i/4e4t4d7fwyov2kzjrwai.png" alt="" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Code Example
&lt;/h1&gt;

&lt;p&gt;But talk is cheap, so we’ll show you a code example. :-)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/r056JQBFkE8QE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/r056JQBFkE8QE/giphy.gif" alt="" width="440" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you have a chaincode example with a method &lt;code&gt;getAsset&lt;/code&gt;. Read through to see how it looks and we’ll explain right afterwards.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;This code is for a smart contract with a method getAsset.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Invoke&lt;/strong&gt; method is the entry point when calling our smart contract via &lt;em&gt;RPC&lt;/em&gt;; if the method is not supported it will return an error.&lt;br&gt;
That would be a very good initial test to check if our test environment is correctly configured. :-)&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;getObjectAsBytes&lt;/strong&gt; method is just used to return a saved object as a response in the method call.&lt;/p&gt;

&lt;p&gt;So going back to the &lt;strong&gt;getAsset&lt;/strong&gt; method, it receives a parameter, which is the ID of the resource and, if it exists, it returns the result as JSON.&lt;/p&gt;

&lt;p&gt;Now you know what the code does, let’s create some tests for this beast, because, as great chefs do, we always need to taste the recipe before serving.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l2YWuhILzuqDcexaw/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l2YWuhILzuqDcexaw/giphy.gif" alt="" width="480" height="204"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Tests
&lt;/h1&gt;

&lt;p&gt;We’re going to &lt;strong&gt;create a test suite with two main test cases&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test when the ID sent doesn’t exist, we’ll assert the error.&lt;/li&gt;
&lt;li&gt;Test when the ID sent does exist, we’ll assert the response is good and an attribute of the object (the name) is present.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We follow &lt;a href="http://wiki.c2.com/?ArrangeActAssert"&gt;AAA (Arrange Act Asset)&lt;/a&gt; principle to see the different parts of the test cases easily. In the different part of the test cases we can see:&lt;/p&gt;

&lt;p&gt;In this case, the &lt;strong&gt;Arrange&lt;/strong&gt; would need to initialize the smart contract “connection” and, in case of a valid id, &lt;strong&gt;create the Asset with its name&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Act&lt;/strong&gt; part of the test, we’ll do mostly the same, use the method name, the ID, and in case of creation or append(edit), the JSON object&lt;br&gt;
with the payload.&lt;/p&gt;

&lt;p&gt;In the &lt;strong&gt;Assert&lt;/strong&gt; we’ll check if the response is &lt;em&gt;OK&lt;/em&gt; or &lt;em&gt;Error&lt;/em&gt;, and we can also check with the variables &lt;strong&gt;res.Message&lt;/strong&gt; or &lt;strong&gt;res.Payload&lt;/strong&gt; if the content&lt;br&gt;
of the response is what the right one.&lt;/p&gt;

&lt;p&gt;That’s it for now! In following articles we’ll talk about how to do BDD for the chaincode, data format manipulation for chaincode methods and Continuous Integration / Continuous Deployment for our chaincode on an Hyperledger Fabric network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/ch1Z4rUWBZBnO/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/ch1Z4rUWBZBnO/giphy.gif" alt="" width="400" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This post was written appeared first on my &lt;a href="https://javaguirre.me/2019/01/21/testing-chaincode-on-hyperledger-fabric"&gt;blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>hyperledger</category>
    </item>
  </channel>
</rss>
