|
11 | 11 | "\n", |
12 | 12 | "## 1. Introduzione ai Test Unitari: Principi e Pratica\n", |
13 | 13 | "\n", |
14 | | - "Il **testing del software** è un processo cruciale che verifica che un programma funzioni come previsto. Non si tratta solo di trovare bug, ma di garantire la qualità, l'affidabilità e la manutenibilità del codice nel tempo. Tra le varie strategie di testing, il **testing unitario** è la più granulare e viene eseguita dagli sviluppatori stessi.\n", |
| 14 | + "Il **testing del software** è un processo cruciale che verifica che un programma funzioni come previsto. Non si tratta solo di trovare bug, ma di garantire la qualità, l'affidabilità e la manutenibilità del codice nel tempo. Tra le varie strategie di testing, il **testing unitario** è la più granulare e riesce ad essere eseguita dagli stessi sviluppatori.\n", |
15 | 15 | "\n", |
16 | 16 | "### Cos'è un Test Unitario?\n", |
17 | 17 | "\n", |
18 | 18 | "Un **test unitario** è una porzione di codice che verifica il comportamento di una singola e isolata \"unità\" del tuo programma. Un'unità può essere una funzione, un metodo di una classe o una singola classe. L'obiettivo è isolare l'unità e assicurarsi che restituisca l'output corretto per un determinato input, in un ambiente controllato.\n", |
19 | 19 | "\n", |
20 | | - "Pensa al testing unitario come all'assemblaggio di un'automobile. Prima di testare l'intera vettura, verifichi che ogni singolo componente, come il motore, i freni o il volante, funzioni perfettamente per conto suo. Se un componente è difettoso, lo individui e lo ripari subito, senza dover smontare l'intera macchina in un secondo momento.\n", |
| 20 | + "Si può pensare al testing unitario come all'assemblaggio di un'automobile. Prima di testare l'intera vettura, verifichi che ogni singolo componente, come il motore, i freni o il volante, funzioni perfettamente per conto suo. Se un componente è difettoso, lo individui e lo ripari subito, senza dover smontare l'intera macchina in un secondo momento.\n", |
21 | 21 | "\n", |
22 | 22 | "### I Principi del Testing Unitario\n", |
23 | 23 | "\n", |
|
31 | 31 | "\n", |
32 | 32 | "### Il Ruolo di `unittest` in Python\n", |
33 | 33 | "\n", |
34 | | - "Python include un modulo integrato chiamato **`unittest`**, ispirato a framework di test di altri linguaggi come JUnit. `unittest` fornisce un set completo di strumenti per costruire e gestire i test unitari senza la necessità di installare librerie esterne. È il punto di partenza ideale per chiunque voglia imparare a testare in Python.\n", |
| 34 | + "Python include un modulo integrato chiamato **`unittest`**, ispirato a framework di test di altri linguaggi come JUnit. `unittest` fornisce un set completo di strumenti per costruire e gestire i test unitari senza la necessità di installare librerie esterne.\n", |
35 | 35 | "\n", |
36 | 36 | "Le sue componenti principali sono:\n", |
37 | 37 | "\n", |
|
59 | 59 | "\n", |
60 | 60 | "```python\n", |
61 | 61 | "# numeri.py\n", |
62 | | - "def is_pari(numero):\n", |
| 62 | + "def is_even(number):\n", |
63 | 63 | " \"\"\"Restituisce True se il numero è pari, altrimenti False.\"\"\"\n", |
64 | | - " return numero % 2 == 0\n", |
| 64 | + " return number % 2 == 0\n", |
65 | 65 | "```\n", |
66 | 66 | "\n", |
67 | 67 | "Per testare questa funzione, creeremo un file `test_numeri.py`:\n", |
68 | 68 | "\n", |
69 | 69 | "```python\n", |
70 | 70 | "# test_numeri.py\n", |
71 | 71 | "import unittest\n", |
72 | | - "from numeri import is_pari\n", |
| 72 | + "from numeri import is_even\n", |
73 | 73 | "\n", |
74 | | - "class TestNumeri(unittest.TestCase):\n", |
| 74 | + "class TestNumbers(unittest.TestCase):\n", |
75 | 75 | " \n", |
76 | | - " def test_pari(self):\n", |
77 | | - " self.assertTrue(is_pari(4), \"4 dovrebbe essere un numero pari\")\n", |
78 | | - " self.assertFalse(is_pari(5), \"5 dovrebbe essere un numero dispari\")\n", |
79 | | - " self.assertTrue(is_pari(0), \"0 dovrebbe essere considerato pari\")\n", |
| 76 | + " def test_even_number(self):\n", |
| 77 | + " self.assertTrue(is_even(4), \"4 should be an even number\")\n", |
| 78 | + " self.assertFalse(is_even(5), \"5 should be an odd number\")\n", |
| 79 | + " self.assertTrue(is_even(0), \"0 should be considered even\")\n", |
80 | 80 | " \n", |
81 | | - " def test_input_negativo(self):\n", |
82 | | - " self.assertTrue(is_pari(-2), \"-2 dovrebbe essere un numero pari\")\n", |
| 81 | + " def test_negative_input(self):\n", |
| 82 | + " self.assertTrue(is_even(-2), \"-2 should be an even number\")\n", |
83 | 83 | "\n", |
84 | 84 | "if __name__ == '__main__':\n", |
85 | 85 | " unittest.main()\n", |
|
117 | 117 | "\n", |
118 | 118 | "```python\n", |
119 | 119 | "# statistiche.py\n", |
120 | | - "def calcola_media(lista_numeri):\n", |
| 120 | + "def calculate_average(list_numbers):\n", |
121 | 121 | " \"\"\"Calcola la media di una lista di numeri.\"\"\"\n", |
122 | | - " if not lista_numeri:\n", |
123 | | - " raise ValueError(\"Impossibile calcolare la media di una lista vuota.\")\n", |
124 | | - " return sum(lista_numeri) / len(lista_numeri)\n", |
| 122 | + " if not list_numbers:\n", |
| 123 | + " raise ValueError(\"Impossible to calculate the average of an empty list.\")\n", |
| 124 | + " return sum(list_numbers) / len(list_numbers)\n", |
125 | 125 | "```\n", |
126 | 126 | "\n", |
127 | 127 | "**Istruzioni per i test:**\n", |
|
139 | 139 | "source": [ |
140 | 140 | "---", |
141 | 141 | "\n", |
142 | | - "### Esercizio 2: Classe `Utente`\n", |
| 142 | + "### Esercizio 2: Classe `User`\n", |
143 | 143 | "\n", |
144 | 144 | "Crea un file `utenti.py` con la seguente classe e scrivi i test per i suoi metodi in `test_utenti.py`.\n", |
145 | 145 | "\n", |
146 | 146 | "```python\n", |
147 | 147 | "# utenti.py\n", |
148 | | - "class Utente:\n", |
149 | | - " def __init__(self, nome, email):\n", |
150 | | - " if not nome or not email:\n", |
151 | | - " raise ValueError(\"Nome ed email non possono essere vuoti.\")\n", |
152 | | - " self.nome = nome\n", |
| 148 | + "class User:\n", |
| 149 | + " def __init__(self, name, email):\n", |
| 150 | + " if not name or not email:\n", |
| 151 | + " raise ValueError(\"Name and email must be not empty.\")\n", |
| 152 | + " self.name = name\n", |
153 | 153 | " self.email = email\n", |
154 | | - " self.loggato = False\n", |
| 154 | + " self.logged = False\n", |
155 | 155 | " \n", |
156 | 156 | " def login(self):\n", |
157 | | - " self.loggato = True\n", |
| 157 | + " self.logged = True\n", |
158 | 158 | " \n", |
159 | 159 | " def logout(self):\n", |
160 | | - " self.loggato = False\n", |
| 160 | + " self.logged = False\n", |
161 | 161 | "```\n", |
162 | 162 | "\n", |
163 | 163 | "**Istruzioni per i test:**\n", |
164 | 164 | "\n", |
165 | | - "1. Verifica che, dopo l'inizializzazione, gli attributi `nome`, `email` siano corretti e `loggato` sia `False`.\n", |
166 | | - "2. Verifica che il metodo `login()` cambi correttamente lo stato di `loggato` a `True`.\n", |
167 | | - "3. Verifica che il metodo `logout()` cambi correttamente lo stato di `loggato` a `False`.\n", |
168 | | - "4. Verifica che l'inizializzazione della classe sollevi un `ValueError` se `nome` o `email` sono stringhe vuote." |
| 165 | + "1. Verifica che, dopo l'inizializzazione, gli attributi `name`, `email` siano corretti e `logged` sia `False`.\n", |
| 166 | + "2. Verifica che il metodo `login()` cambi correttamente lo stato di `logged` a `True`.\n", |
| 167 | + "3. Verifica che il metodo `logout()` cambi correttamente lo stato di `logged` a `False`.\n", |
| 168 | + "4. Verifica che l'inizializzazione della classe sollevi un `ValueError` se `name` o `email` sono stringhe vuote." |
169 | 169 | ] |
170 | 170 | }, |
171 | 171 | { |
|
197 | 197 | "source": [ |
198 | 198 | "# test_statistiche.py\n", |
199 | 199 | "import unittest\n", |
200 | | - "from statistiche import calcola_media\n", |
| 200 | + "from statistiche import calculate_average\n", |
201 | 201 | "\n", |
202 | | - "class TestStatistiche(unittest.TestCase):\n", |
| 202 | + "class TestStats(unittest.TestCase):\n", |
203 | 203 | " \n", |
204 | | - " def test_media_interi(self):\n", |
205 | | - " self.assertEqual(calcola_media([1, 2, 3, 4, 5]), 3.0)\n", |
| 204 | + " def test_average_on_ints(self):\n", |
| 205 | + " self.assertEqual(calculate_average([1, 2, 3, 4, 5]), 3.0)\n", |
206 | 206 | " \n", |
207 | | - " def test_media_float(self):\n", |
208 | | - " self.assertEqual(calcola_media([1.5, 2.5, 3.5]), 2.5)\n", |
| 207 | + " def test_average_on_floats(self):\n", |
| 208 | + " self.assertEqual(calculate_average([1.5, 2.5, 3.5]), 2.5)\n", |
209 | 209 | "\n", |
210 | | - " def test_lista_vuota_solleva_eccezione(self):\n", |
| 210 | + " def test_empty_list(self):\n", |
211 | 211 | " with self.assertRaises(ValueError):\n", |
212 | | - " calcola_media([])\n", |
| 212 | + " calculate_average([])\n", |
213 | 213 | "\n", |
214 | | - " def test_lista_singolo_elemento(self):\n", |
215 | | - " self.assertEqual(calcola_media([10]), 10.0)\n", |
| 214 | + " def test_list_with_single_element(self):\n", |
| 215 | + " self.assertEqual(calculate_average([10]), 10.0)\n", |
216 | 216 | "\n", |
217 | 217 | "if __name__ == '__main__':\n", |
218 | 218 | " unittest.main()" |
|
223 | 223 | "id": "e3c30fe5", |
224 | 224 | "metadata": {}, |
225 | 225 | "source": [ |
226 | | - "### Soluzione Esercizio 2: Test per la classe `Utente`\n", |
| 226 | + "### Soluzione Esercizio 2: Test per la classe `User`\n", |
227 | 227 | "\n", |
228 | 228 | "Copia questo codice in un file `test_utenti.py`." |
229 | 229 | ] |
|
237 | 237 | "source": [ |
238 | 238 | "# test_utenti.py\n", |
239 | 239 | "import unittest\n", |
240 | | - "from utenti import Utente\n", |
| 240 | + "from utenti import User\n", |
241 | 241 | "\n", |
242 | | - "class TestUtente(unittest.TestCase):\n", |
| 242 | + "class TestUser(unittest.TestCase):\n", |
243 | 243 | " \n", |
244 | 244 | " def setUp(self):\n", |
245 | 245 | " # Questo metodo viene eseguito prima di ogni test. \n", |
246 | 246 | " # È utile per creare un'istanza \"pulita\" della classe da testare.\n", |
247 | | - " self.utente_valido = Utente(\"Mario Rossi\", \"[email protected]\")\n", |
| 247 | + " self.valid_user = User(\"Mario Rossi\", \"[email protected]\")\n", |
248 | 248 | " \n", |
249 | | - " def test_inizializzazione_corretta(self):\n", |
250 | | - " self.assertEqual(self.utente_valido.nome, \"Mario Rossi\")\n", |
251 | | - " self.assertEqual(self.utente_valido.email, \"[email protected]\")\n", |
252 | | - " self.assertFalse(self.utente_valido.loggato)\n", |
| 249 | + " def test_init_ok(self):\n", |
| 250 | + " self.assertEqual(self.valid_user.name, \"Mario Rossi\")\n", |
| 251 | + " self.assertEqual(self.valid_user.email, \"[email protected]\")\n", |
| 252 | + " self.assertFalse(self.valid_user.logged)\n", |
253 | 253 | " \n", |
254 | 254 | " def test_login(self):\n", |
255 | | - " self.utente_valido.login()\n", |
256 | | - " self.assertTrue(self.utente_valido.loggato)\n", |
| 255 | + " self.valid_user.login()\n", |
| 256 | + " self.assertTrue(self.valid_user.logged)\n", |
257 | 257 | " \n", |
258 | 258 | " def test_logout(self):\n", |
259 | | - " self.utente_valido.login() \n", |
260 | | - " self.utente_valido.logout()\n", |
261 | | - " self.assertFalse(self.utente_valido.loggato)\n", |
| 259 | + " self.valid_user.login() \n", |
| 260 | + " self.valid_user.logout()\n", |
| 261 | + " self.assertFalse(self.valid_user.logged)\n", |
262 | 262 | " \n", |
263 | | - " def test_inizializzazione_con_valori_vuoti_solleva_eccezione(self):\n", |
| 263 | + " def test_init_empty_values(self):\n", |
264 | 264 | " with self.assertRaises(ValueError):\n", |
265 | | - " Utente(\"\", \"[email protected]\")\n", |
| 265 | + " User(\"\", \"[email protected]\")\n", |
266 | 266 | " \n", |
267 | 267 | " with self.assertRaises(ValueError):\n", |
268 | | - " Utente(\"Nome\", \"\")\n", |
| 268 | + " User(\"Name\", \"\")\n", |
269 | 269 | "\n", |
270 | 270 | "if __name__ == '__main__':\n", |
271 | 271 | " unittest.main()\n" |
|
0 commit comments