Skip to content

Commit

Permalink
deploy: 7e37de7
Browse files Browse the repository at this point in the history
  • Loading branch information
baniasbaabe committed Dec 30, 2023
1 parent 4de2779 commit 30d8872
Show file tree
Hide file tree
Showing 5 changed files with 181 additions and 1 deletion.
50 changes: 50 additions & 0 deletions _sources/book/pythontricks/Chapter.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,56 @@
"p = Point(x=3.2, y=1.0)\n",
"print(p.x, p.y)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Mutable Default Values for Function Arguments"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"One big mistake in Python:\n",
"\n",
"Using mutable default values for function arguments.\n",
"\n",
"When using mutable objects like a list as a default value, you have to be careful.\n",
"\n",
"See the example below, where the default list is shared among all calls to the function.\n",
"\n",
"To fix this, set the default value to None and create a new list inside the function if no list is provided."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Dangerous behaviour:\n",
"def increment_numbers(numbers=[]):\n",
" for i in range(3):\n",
" numbers.append(i)\n",
" print(f\"Numbers: {numbers}\")\n",
"\n",
"increment_numbers() # Output: Numbers: [0, 1, 2]\n",
"increment_numbers() # Output: Numbers: [0, 1, 2, 0, 1, 2]\n",
"\n",
"\n",
"# Better:\n",
"def increment_numbers(numbers=None):\n",
" if numbers is None:\n",
" numbers = []\n",
" for i in range(3):\n",
" numbers.append(i)\n",
" print(f\"Numbers: {numbers}\")\n",
"\n",
"increment_numbers() # Output: Numbers: [0, 1, 2]\n",
"increment_numbers() # Output: Numbers: [0, 1, 2]"
]
}
],
"metadata": {
Expand Down
64 changes: 64 additions & 0 deletions _sources/book/testing/Chapter.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,70 @@
"def test_addition_commutative(a, b):\n",
" assert a + b == b + a"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Mocking Dependencies with `pytest-mock`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Testing is an essential part of Software projects.\n",
"\n",
"\n",
"\n",
"Especially unit testing, where you test the smallest piece of code that can be isolated.\n",
"\n",
"\n",
"\n",
"They should be independent, and fast & cheap to execute.\n",
"\n",
"\n",
"\n",
"But, what if you have some dependencies like API calls or interactions with databases and systems?\n",
"\n",
"\n",
"\n",
"Here's where mocking comes into play.\n",
"\n",
"\n",
"\n",
"Mocking allows you to replace dependencies and real objects with fake ones which mimic the real behavior.\n",
"\n",
"\n",
"\n",
"So, you don't have to rely on the availability of your API, or ask for permission to interact with a database, but you can test your functions isolated and independently.\n",
"\n",
"\n",
"\n",
"In Python, you can perform mocking with `pytest-mock`, a wrapper around the built-in mock functionality of Python.\n",
"\n",
"\n",
"\n",
"See the example below, where we mock the file removal functionality. We can test it without deleting a file from the disk."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"\n",
"class UnixFS:\n",
" @staticmethod\n",
" def rm(filename):\n",
" os.remove(filename)\n",
"def test_unix_fs(mocker):\n",
" mocker.patch('os.remove')\n",
" UnixFS.rm('file')\n",
" os.remove.assert_called_once_with('file')\n"
]
}
],
"metadata": {
Expand Down
36 changes: 36 additions & 0 deletions book/pythontricks/Chapter.html
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ <h2> Contents </h2>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#count-occurrences-in-an-iterable-with-counter">10.1.18. Count Occurrences in an Iterable with <code class="docutils literal notranslate"><span class="pre">Counter</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#set-default-values-for-dictionaries-with-defaultdict">10.1.19. Set Default Values for Dictionaries with <code class="docutils literal notranslate"><span class="pre">defaultdict</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#more-structured-tuples-with-namedtuple">10.1.20. More Structured Tuples with <code class="docutils literal notranslate"><span class="pre">namedtuple</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#mutable-default-values-for-function-arguments">10.1.21. Mutable Default Values for Function Arguments</a></li>
</ul>
</nav>
</div>
Expand Down Expand Up @@ -934,6 +935,40 @@ <h2><span class="section-number">10.1.20. </span>More Structured Tuples with <co
</div>
</div>
</section>
<section id="mutable-default-values-for-function-arguments">
<h2><span class="section-number">10.1.21. </span>Mutable Default Values for Function Arguments<a class="headerlink" href="#mutable-default-values-for-function-arguments" title="Permalink to this heading">#</a></h2>
<p>One big mistake in Python:</p>
<p>Using mutable default values for function arguments.</p>
<p>When using mutable objects like a list as a default value, you have to be careful.</p>
<p>See the example below, where the default list is shared among all calls to the function.</p>
<p>To fix this, set the default value to None and create a new list inside the function if no list is provided.</p>
<div class="cell docutils container">
<div class="cell_input docutils container">
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># Dangerous behaviour:</span>
<span class="k">def</span> <span class="nf">increment_numbers</span><span class="p">(</span><span class="n">numbers</span><span class="o">=</span><span class="p">[]):</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
<span class="n">numbers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Numbers: </span><span class="si">{</span><span class="n">numbers</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>

<span class="n">increment_numbers</span><span class="p">()</span> <span class="c1"># Output: Numbers: [0, 1, 2]</span>
<span class="n">increment_numbers</span><span class="p">()</span> <span class="c1"># Output: Numbers: [0, 1, 2, 0, 1, 2]</span>


<span class="c1"># Better:</span>
<span class="k">def</span> <span class="nf">increment_numbers</span><span class="p">(</span><span class="n">numbers</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">numbers</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">numbers</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">):</span>
<span class="n">numbers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Numbers: </span><span class="si">{</span><span class="n">numbers</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>

<span class="n">increment_numbers</span><span class="p">()</span> <span class="c1"># Output: Numbers: [0, 1, 2]</span>
<span class="n">increment_numbers</span><span class="p">()</span> <span class="c1"># Output: Numbers: [0, 1, 2]</span>
</pre></div>
</div>
</div>
</div>
</section>
</section>

<script type="text/x-thebe-config">
Expand Down Expand Up @@ -1023,6 +1058,7 @@ <h2><span class="section-number">10.1.20. </span>More Structured Tuples with <co
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#count-occurrences-in-an-iterable-with-counter">10.1.18. Count Occurrences in an Iterable with <code class="docutils literal notranslate"><span class="pre">Counter</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#set-default-values-for-dictionaries-with-defaultdict">10.1.19. Set Default Values for Dictionaries with <code class="docutils literal notranslate"><span class="pre">defaultdict</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#more-structured-tuples-with-namedtuple">10.1.20. More Structured Tuples with <code class="docutils literal notranslate"><span class="pre">namedtuple</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#mutable-default-values-for-function-arguments">10.1.21. Mutable Default Values for Function Arguments</a></li>
</ul>
</nav></div>

Expand Down
30 changes: 30 additions & 0 deletions book/testing/Chapter.html
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ <h2> Contents </h2>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#instantly-show-errors-in-your-test-suite">13.1.5. Instantly show errors in your Test Suite</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#limit-pytest-s-output-to-a-minimum">13.1.6. Limit pytest’s output to a minimum</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#property-based-testing-with-hypothesis">13.1.7. Property-based Testing with <code class="docutils literal notranslate"><span class="pre">hypothesis</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#mocking-dependencies-with-pytest-mock">13.1.8. Mocking Dependencies with <code class="docutils literal notranslate"><span class="pre">pytest-mock</span></code></a></li>
</ul>
</nav>
</div>
Expand Down Expand Up @@ -645,6 +646,34 @@ <h2><span class="section-number">13.1.7. </span>Property-based Testing with <cod
</div>
</div>
</section>
<section id="mocking-dependencies-with-pytest-mock">
<h2><span class="section-number">13.1.8. </span>Mocking Dependencies with <code class="docutils literal notranslate"><span class="pre">pytest-mock</span></code><a class="headerlink" href="#mocking-dependencies-with-pytest-mock" title="Permalink to this heading">#</a></h2>
<p>Testing is an essential part of Software projects.</p>
<p>Especially unit testing, where you test the smallest piece of code that can be isolated.</p>
<p>They should be independent, and fast &amp; cheap to execute.</p>
<p>But, what if you have some dependencies like API calls or interactions with databases and systems?</p>
<p>Here’s where mocking comes into play.</p>
<p>Mocking allows you to replace dependencies and real objects with fake ones which mimic the real behavior.</p>
<p>So, you don’t have to rely on the availability of your API, or ask for permission to interact with a database, but you can test your functions isolated and independently.</p>
<p>In Python, you can perform mocking with <code class="docutils literal notranslate"><span class="pre">pytest-mock</span></code>, a wrapper around the built-in mock functionality of Python.</p>
<p>See the example below, where we mock the file removal functionality. We can test it without deleting a file from the disk.</p>
<div class="cell docutils container">
<div class="cell_input docutils container">
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">os</span>

<span class="k">class</span> <span class="nc">UnixFS</span><span class="p">:</span>
<span class="nd">@staticmethod</span>
<span class="k">def</span> <span class="nf">rm</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_unix_fs</span><span class="p">(</span><span class="n">mocker</span><span class="p">):</span>
<span class="n">mocker</span><span class="o">.</span><span class="n">patch</span><span class="p">(</span><span class="s1">&#39;os.remove&#39;</span><span class="p">)</span>
<span class="n">UnixFS</span><span class="o">.</span><span class="n">rm</span><span class="p">(</span><span class="s1">&#39;file&#39;</span><span class="p">)</span>
<span class="n">os</span><span class="o">.</span><span class="n">remove</span><span class="o">.</span><span class="n">assert_called_once_with</span><span class="p">(</span><span class="s1">&#39;file&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</div>
</section>
</section>

<script type="text/x-thebe-config">
Expand Down Expand Up @@ -721,6 +750,7 @@ <h2><span class="section-number">13.1.7. </span>Property-based Testing with <cod
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#instantly-show-errors-in-your-test-suite">13.1.5. Instantly show errors in your Test Suite</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#limit-pytest-s-output-to-a-minimum">13.1.6. Limit pytest’s output to a minimum</a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#property-based-testing-with-hypothesis">13.1.7. Property-based Testing with <code class="docutils literal notranslate"><span class="pre">hypothesis</span></code></a></li>
<li class="toc-h2 nav-item toc-entry"><a class="reference internal nav-link" href="#mocking-dependencies-with-pytest-mock">13.1.8. Mocking Dependencies with <code class="docutils literal notranslate"><span class="pre">pytest-mock</span></code></a></li>
</ul>
</nav></div>

Expand Down
2 changes: 1 addition & 1 deletion searchindex.js

Large diffs are not rendered by default.

0 comments on commit 30d8872

Please sign in to comment.