Using_Python_to_Interact_wi.../module5.ipynb
2025-01-27 12:49:32 +03:00

241 lines
8.4 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Simple Tests"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Unit Tests"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Concepts**\n",
"\n",
"Unittest relies on the following concepts:\n",
"\n",
"- **Test fixture:** This refers to preparing to perform one or more tests. In addition, test fixtures also include any actions involved in testing cleanup. This could involve creating temporary or proxy databases, directories, or starting a server process.\n",
"- **Test case:** This is the individual unit of testing that looks for a specific response to a set of inputs. If needed, TestCase is a base class provided by unittest and can be used to create new test cases.\n",
"- **Test suite:** This is a collection of test cases, test suites, or a combination of both. It is used to compile tests that should be executed together.\n",
"- **Test runner:** This runs the test and provides developers with the outcomes data. The test runner can use different interfaces, like graphical or textual, to provide the developer with the test results. It can also provide a special value to developers to communicate the test results. "
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(['flour', 'sugar', 'eggs', 'cocoa', 'sprinkles', 'cherries'], 14)"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"from typing import List\n",
"\n",
"\n",
"class CakeFactory:\n",
" def __init__(self, cake_type: str, size: str):\n",
" self.cake_type = cake_type\n",
" self.size = size\n",
" self.toppings = []\n",
"\n",
" # Price based on cake type and size\n",
" self.price = 10 if self.cake_type == \"chocolate\" else 8\n",
" self.price += 2 if self.size == \"medium\" else 4 if self.size == \"large\" else 0\n",
"\n",
" def add_topping(self, topping: str):\n",
" self.toppings.append(topping)\n",
" # Adding 1 to the price for each topping\n",
" self.price += 1\n",
"\n",
" def check_ingredients(self) -> List[str]:\n",
" ingredients = ['flour', 'sugar', 'eggs']\n",
" ingredients.append('cocoa') if self.cake_type == \"chocolate\" else ingredients.append('vanilla extract')\n",
" ingredients += self.toppings\n",
" return ingredients\n",
"\n",
" def check_price(self) -> float:\n",
" return self.price\n",
"\n",
"# Example of creating a cake and adding toppings\n",
"cake = CakeFactory(\"chocolate\", \"medium\")\n",
"cake.add_topping(\"sprinkles\")\n",
"cake.add_topping(\"cherries\")\n",
"cake_ingredients = cake.check_ingredients()\n",
"cake_price = cake.check_price()\n",
"\n",
"\n",
"cake_ingredients, cake_price"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import unittest\n",
"\n",
"class TestCakeFactory(unittest.TestCase):\n",
" def test_create_cake(self):\n",
" cake = CakeFactory(\"vanilla\", \"small\")\n",
" self.assertEqual(cake.cake_type, \"vanilla\")\n",
" self.assertEqual(cake.size, \"small\")\n",
" self.assertEqual(cake.price, 8) # Vanilla cake, small size\n",
"\n",
" def test_add_topping(self):\n",
" cake = CakeFactory(\"chocolate\", \"large\")\n",
" cake.add_topping(\"sprinkles\")\n",
" self.assertIn(\"sprinkles\", cake.toppings)\n",
"\n",
" def test_check_ingredients(self):\n",
" cake = CakeFactory(\"chocolate\", \"medium\")\n",
" cake.add_topping(\"cherries\")\n",
" ingredients = cake.check_ingredients()\n",
" self.assertIn(\"cocoa\", ingredients)\n",
" self.assertIn(\"cherries\", ingredients)\n",
" self.assertNotIn(\"vanilla extract\", ingredients)\n",
"\n",
" def test_check_price(self):\n",
" cake = CakeFactory(\"vanilla\", \"large\")\n",
" cake.add_topping(\"sprinkles\")\n",
" cake.add_topping(\"cherries\")\n",
" price = cake.check_price()\n",
" self.assertEqual(price, 13) # Vanilla cake, large size + 2 toppings\n",
"\n",
"\n",
"# Running the unittests\n",
"unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(TestCakeFactory))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## pytest"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pytest\n",
"class Fruit:\n",
" def __init__(self, name):\n",
" self.name = name\n",
" self.cubed = False\n",
"\n",
"\n",
" def cube(self):\n",
" self.cubed = True\n",
"\n",
"\n",
"class FruitSalad:\n",
" def __init__(self, *fruit_bowl):\n",
" self.fruit = fruit_bowl\n",
" self._cube_fruit()\n",
"\n",
"\n",
" def _cube_fruit(self):\n",
" for fruit in self.fruit:\n",
" fruit.cube()\n",
"\n",
"\n",
"# Arrange\n",
"@pytest.fixture\n",
"def fruit_bowl():\n",
" return [Fruit(\"apple\"), Fruit(\"banana\")]\n",
"\n",
"\n",
"def test_fruit_salad(fruit_bowl):\n",
" # Act\n",
" fruit_salad = FruitSalad(*fruit_bowl)\n",
"\n",
"\n",
" # Assert\n",
" assert all(fruit.cubed for fruit in fruit_salad.fruit)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Comparing unittest and pytest"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Both unittest and pytest provide developers with tools to create robust and reliable code through different forms of tests. Both can be used while creating programs within Python, and it is the developers preference on which type they want to use.\n",
"\n",
"In this reading, you will learn about the differences between unittest and pytest, and when to use them.\n",
"\n",
"**Key differences**\n",
"\n",
"Unittest is a tool that is built directly into Python, while pytest must be imported from outside your script. Test discovery acts differently for each test type. Unittest has the functionality to automatically detect test cases within an application, but it must be called from the command line. Pytests are performed automatically using the prefix test_. Unittests use an object-oriented approach to write tests, while pytests use a functional approach. Pytests use built-in assert statements, making tests easier to read and write. On the other hand, unittests provide special assert methods like assertEqual() or assertTrue().\n",
"\n",
"Backward compatibility exists between unittest and pytest. Because unittest is built directly into Python, these test suites are more easily executed. But that doesnt mean that pytest cannot be executed. Because of backward compatibility, the unittest framework can be seamlessly executed using the pytest framework without major modifications. This allows developers to adopt pytest gradually and integrate them into their code.\n",
"\n",
"**Key takeaways**\n",
"\n",
"Unittest and pytest are both beneficial to developers in executing tests on their code written in Python. Each one has its pros and cons, and it is up to the developer and their preference on which type of testing framework they want to use. "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"#!/usr/bin/env python3\n",
"import re\n",
"def rearrange_name(name):\n",
" result = re.search(r\"^([\\w .]*), ([\\w .]*)$\", name)\n",
" return \"{} {}\".format(result[2], result[1])\n",
"from rearrange import rearrange_name\n",
"\n",
"rearrange_name(\"Lovelace, Ada\") "
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}