<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pablo Aguilar</title>
    <description>The latest articles on DEV Community by Pablo Aguilar (@thepabloaguilar).</description>
    <link>https://dev.to/thepabloaguilar</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%2F257631%2F358b1850-8c61-4c11-abe9-306385d4ff3c.jpeg</url>
      <title>DEV Community: Pablo Aguilar</title>
      <link>https://dev.to/thepabloaguilar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thepabloaguilar"/>
    <language>en</language>
    <item>
      <title>It's not just a Pull Request</title>
      <dc:creator>Pablo Aguilar</dc:creator>
      <pubDate>Tue, 23 Feb 2021 12:16:33 +0000</pubDate>
      <link>https://dev.to/thepabloaguilar/it-s-not-just-a-pull-request-21</link>
      <guid>https://dev.to/thepabloaguilar/it-s-not-just-a-pull-request-21</guid>
      <description>&lt;p&gt;In all my professional experiences so far I've seen a lot of people/teams ignoring the meaning behind a Pull Request (PR), treating it like a kind of bureaucracy to deploy their piece of code.&lt;/p&gt;

&lt;p&gt;Sometimes I heard people saying to each other: "I'll open a PR, just accept it because everything is fine". In the end that accepted PR crashed the entire system, I can say that reviewer was as wrong as the reviewee because he was negligent!&lt;/p&gt;

&lt;p&gt;We can't automate everything, people think by using &lt;strong&gt;automated tests&lt;/strong&gt; they don't have to do anything else to guarantee the code quality.&lt;/p&gt;

&lt;p&gt;By &lt;strong&gt;automated tests&lt;/strong&gt; I mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unit Tests, Integration Tests, etc.&lt;/li&gt;
&lt;li&gt;Static Tests (linters)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sobolevn.me/2019/08/testing-mypy-types"&gt;Static Typing Tests&lt;/a&gt; (if you're using a language with optional static type like Python)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In the next topics, I'll try to explain my point of view about code and its quality in the business world!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the code?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Every project/codebase is a company's asset.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code we write isn't ours, the code belongs to the company. We're just momentarily responsible for it, perhaps in a few weeks the project goes to another team, and also another project can reach our team!&lt;/p&gt;

&lt;p&gt;Due to the fact that projects can be moved around teams, it's our duty to maintain the quality of the code we write, we need to care about it not because someone wants but because we should, it's a task for everyone who writes code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quality
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Quality is an empathy thing with who maintained, maintains and will maintain the code.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many people think that automated tests are enough to guarantee quality but the equation should be something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;quality = automated tests + legibility + maintainability + good architecture&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Why does the review process exist in the Pull Request if I can automatically merge it after a successful pipeline?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because we can't guarantee legibility, maintainability, and good architecture. People think that running a linter and having 100% code coverage is enough but it isn't.&lt;/p&gt;

&lt;p&gt;Remember, code coverage doesn't mean test quality!&lt;/p&gt;

&lt;p&gt;As a team, we're responsible for the code in the &lt;strong&gt;&lt;em&gt;main&lt;/em&gt;&lt;/strong&gt; branch. When someone creates other branches to implement a new feature or fix some bug who created the branch and the reviewer are responsible to guarantee the quality of the code that will be merged into the &lt;strong&gt;&lt;em&gt;main&lt;/em&gt;&lt;/strong&gt; branch.&lt;/p&gt;

&lt;p&gt;Some people say that code is just a way to reach the product, but if that code doesn't have quality and definition, what will this mean to the final product?&lt;/p&gt;

&lt;p&gt;Probably a product that no one will want to maintain because it'll be hard to understand how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pull Request
&lt;/h2&gt;

&lt;p&gt;A Pull Request is a request to add/change the company's asset, it's something that can be in production already, so, we need to guarantee high quality because our customers will be directly affected.&lt;/p&gt;

&lt;p&gt;The Pull Request is where we can validate every quality aspect of the code that will be merged into the &lt;strong&gt;&lt;em&gt;main&lt;/em&gt;&lt;/strong&gt; branch, trying to reduce any possible mistakes in the code!&lt;/p&gt;

&lt;p&gt;One of the most exciting things about Pull Requests is that everyone learns something from both sides (reviewer and reviewee).&lt;/p&gt;




&lt;p&gt;Special Thanks to people who reviewed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sobolevn"&gt;Nikita Sobolevn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/millengustavo"&gt;Gustavo Millen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bruno-delfino1995"&gt;Bruno Delfino&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Already published on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://thepabloaguilar.medium.com/its-not-just-a-pull-request-9ee42cc080e"&gt;Medium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>codequality</category>
      <category>softwareengineering</category>
      <category>codereview</category>
      <category>pullrequest</category>
    </item>
    <item>
      <title>Monkey Patching is not too bad</title>
      <dc:creator>Pablo Aguilar</dc:creator>
      <pubDate>Thu, 13 Aug 2020 05:14:58 +0000</pubDate>
      <link>https://dev.to/thepabloaguilar/monkey-patching-is-not-too-bad-50e5</link>
      <guid>https://dev.to/thepabloaguilar/monkey-patching-is-not-too-bad-50e5</guid>
      <description>&lt;h2&gt;
  
  
  History
&lt;/h2&gt;

&lt;p&gt;A few months ago I've started to contribute with &lt;a href="https://github.com/dry-python/returns"&gt;returns&lt;/a&gt;, an amazing Open Source Python library with a lot of containers to help us in many ways, I won't cover those containers here but you can access the &lt;a href="https://returns.readthedocs.io/en/latest/"&gt;documentation&lt;/a&gt; page to know more about them.&lt;/p&gt;

&lt;p&gt;Here I'm going to cover why we chose the monkey patching technique to implements a feature, &lt;a href="https://github.com/dry-python/returns/issues/409"&gt;&lt;em&gt;Improve Failure Traceability&lt;/em&gt;&lt;/a&gt;, to the &lt;strong&gt;Result&lt;/strong&gt; containers.&lt;/p&gt;

&lt;p&gt;Just a brief explanation of what is a &lt;a href="https://returns.readthedocs.io/en/latest/pages/result.html"&gt;Result&lt;/a&gt; container, basically your code can take two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Success, the function computation was successfully executed&lt;/li&gt;
&lt;li&gt;Failure, the function computation broke due to business logic or an Exception was raised&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That container abstracts those ways for us, see the example below:&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;from&lt;/span&gt; &lt;span class="nn"&gt;returns.result&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Success&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&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;arg&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;    
&lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;is_even&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;em&gt;Result&lt;/em&gt; can be a great idea because you don't have more to deal with raised Business Exceptions and put &lt;code&gt;try...except&lt;/code&gt; everywhere in our code, we just have to return a Failure container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracing Failure: feature explanation
&lt;/h2&gt;

&lt;p&gt;Failure is great, but &lt;em&gt;Exceptions&lt;/em&gt; give to us an important thing: &lt;strong&gt;where it was raised&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Inspired by &lt;a href="https://dry-rb.org/gems/dry-monads/1.3/tracing-failures/"&gt;Tracing Failure&lt;/a&gt; feature from &lt;a href="https://dry-rb.org/"&gt;dry-rb&lt;/a&gt;, that is a collection of Ruby Libraries, we started the discussion to give this option to the &lt;em&gt;returns&lt;/em&gt; users and one important thing was considered to implement it, &lt;strong&gt;users that will not use this feature can't have their system/application performance affected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The simple, easiest and unique (I guess) way to implement the feature is to get the call stack and make some manipulation with it. In Python is simple to get the call stack, but it's a heavy operation that can affect the performance if it's often called. Below you can see extracted metrics about memory consumption when creating &lt;em&gt;Failure&lt;/em&gt; container getting the call stack and don't getting it, respectively:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Mknzr7lc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r9lpuy2biunjzy9gp1f5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Mknzr7lc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r9lpuy2biunjzy9gp1f5.png" alt="Memory consumption without trace implemented"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fa50m9SR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fj8gdjub2kj7cmsna9be.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fa50m9SR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fj8gdjub2kj7cmsna9be.png" alt="Memory consumption with trace implemented"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How can we implement the tracing feature?
&lt;/h2&gt;

&lt;p&gt;We already know the tracing has to be optional because users that won't use it can't be affected, and as we can see when the trace is enabled we have a huge memory overhead!&lt;/p&gt;

&lt;p&gt;To get the trace optional we had two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use an environment variable&lt;/li&gt;
&lt;li&gt;Use monkey patching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the title of this article you know might we have chosen the second option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Why monkey patching?&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Monkey Patching is a more sophisticated and elegant approach than an environment variable, we can separate in the right way the tracing feature code from the class we want to be traced and we don't depend on an external resource. Using an env variable will end up with something like this in our classes, we can decouple the &lt;strong&gt;&lt;em&gt;if&lt;/em&gt;&lt;/strong&gt; statement from the class but in somewhere of our code the &lt;strong&gt;&lt;em&gt;if&lt;/em&gt;&lt;/strong&gt; will be there:&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="nn"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&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;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'RETURNS_TRACE'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_tracking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Monkey patching is a known friend of Python programmers, we use it a lot while writing tests to mock everything we want (e.g. API request, database interaction), but it's not used too much in our &lt;em&gt;"production"&lt;/em&gt; code because have some drawbacks like it's not &lt;strong&gt;Thread Safe&lt;/strong&gt; and can create many bugs since it can affect our entire code base at runtime. But we understood that tracing feature is to development purposes, we don't care about thread safety problem and we know exactly we are monkey patching!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can we turn the monkey patching technique thread safe in Python?&lt;br&gt;
Yes, we can but it's a subject for another article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After some discussions, we finally delivered our &lt;a href="https://returns.readthedocs.io/en/latest/pages/development.html#tracing-failures"&gt;Tracing Failures&lt;/a&gt; feature, and now users can active explicit in their code the tracing for the Result containers.&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;from&lt;/span&gt; &lt;span class="nn"&gt;returns.result&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;returns.primitives.tracing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;collect_traces&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;collect_traces&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;failure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'example'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;trace_line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;failure&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;trace_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;trace_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lineno&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; in `&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;trace_line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;`"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output should be something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/returns/returns/result.py:529 in `Failure`
/example_folder/example.py:5 in `get_failure`
/example_folder/example.py:1 in `&amp;lt;module&amp;gt;`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Extra
&lt;/h2&gt;

&lt;p&gt;The main goal of &lt;strong&gt;&lt;em&gt;tracing&lt;/em&gt;&lt;/strong&gt; feature is to give to the user the ability to find where the failure occurred, but if you don't want to analyze the call stack and know the scenario where the failure occurs use &lt;a href="https://returns.readthedocs.io/en/latest/pages/contrib/pytest_plugins.html"&gt;returns &lt;strong&gt;&lt;em&gt;pytest&lt;/em&gt;&lt;/strong&gt; plugin&lt;/a&gt; to verify your hypothesis. We provide a fixture called &lt;strong&gt;returns&lt;/strong&gt; with &lt;strong&gt;has_trace&lt;/strong&gt; method, see the example below:&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;from&lt;/span&gt; &lt;span class="nn"&gt;returns.result&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;example_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&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;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;isnumeric&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'"{0}" is not a number'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_if_failure_is_created_at_example_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;has_trace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Failure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;example_function&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;Success&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'not a number'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;example_function&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;test_if_failure_is_created_at_example_functions&lt;/code&gt; fails we know the &lt;strong&gt;failure&lt;/strong&gt; is not created at &lt;code&gt;example_function&lt;/code&gt; or in its internal calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pt.slideshare.net/GrahamDumpleton/hear-no-evil-see-no-evil-patch-no-evil-or-how-to-monkeypatch-safely"&gt;Hear no evil, see no evil, patch no evil: Or, how to monkey-patch safely.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.pythonforthelab.com/blog/monkey-patching-and-its-consequences/"&gt;Monkey Patching and its consequences&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Already published on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://medium.com/@thepabloaguilar/monkey-patching-is-not-too-bad-57418951f2c4"&gt;Medium&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>python3</category>
      <category>monkeypatching</category>
      <category>drypython</category>
    </item>
  </channel>
</rss>
