informatica:programacion:python:cursos:introduccion_programacion_python:ejemplos_practicos
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| informatica:programacion:python:cursos:introduccion_programacion_python:ejemplos_practicos [2023/04/27 09:45] – [Testing: Pruebas unitarias] tempwin | informatica:programacion:python:cursos:introduccion_programacion_python:ejemplos_practicos [2023/04/28 11:47] (actual) – [JSON en Python] tempwin | ||
|---|---|---|---|
| Línea 420: | Línea 420: | ||
| </ | </ | ||
| - | ==== Testing: Pruebas unitarias ===== | + | ===== Testing: Pruebas unitarias ===== |
| Usaremos el módulo [[https:// | Usaremos el módulo [[https:// | ||
| + | |||
| + | Los tests unitarios están pensados para probar módulos aislados. | ||
| Partimos de un programa: | Partimos de un programa: | ||
| <code python> | <code python> | ||
| + | # Programa para resolver ecuaciones de segundo grado con soluciones reales | ||
| from math import sqrt | from math import sqrt | ||
| # Cálculo de las raíces | # Cálculo de las raíces | ||
| - | def segundo_grado(a, | + | def segundo_grado(a: float, b: float, c: float) -> tuple: |
| + | |||
| + | """ | ||
| + | Calcula las soluciones reales de una ecuación de segundo grado. | ||
| + | Devuelve una tupla con las 2 soluciones reales o lanza una excepción | ||
| + | en caso de no tenerlas. | ||
| + | """ | ||
| d = b ** 2 - 4 * a *c | d = b ** 2 - 4 * a *c | ||
| Línea 476: | Línea 485: | ||
| self.assertEqual(segundo_grado(1, | self.assertEqual(segundo_grado(1, | ||
| + | def test_ecuacion4(self): | ||
| + | self.assertAlmostEqual(segundo_grado(1, | ||
| + | |||
| + | # Para probar algo que falle: | ||
| + | def test_ecuacion5(self): | ||
| + | with self.assertRaises(ValueError) as err: | ||
| + | segundo_grado(1, | ||
| + | self.assertTrue(str(err).endswith(" | ||
| + | | ||
| + | def test_ecuacion6(self): | ||
| + | self.assertAlmostEqual(segundo_grado(2, | ||
| + | |||
| + | def test_ecuacion7(self): | ||
| + | self.assertAlmostEqual(segundo_grado(1, | ||
| + | |||
| + | def test_ecuacion8(self): | ||
| + | | ||
| if __name__ == ' | if __name__ == ' | ||
| unittest.main() | unittest.main() | ||
| </ | </ | ||
| + | |||
| + | Si hacemos modificaciones en el código, los tests nos aseguran que todo siga funcionando correctamente o que el cambio que hemos hecho hace que no pasen los test. De esa manera, podremos detectar si algo hemos hecho mal. | ||
| + | |||
| + | Además, al hacer tests, estamos dejando por escrito las pruebas que realizaremos en nuestro código. | ||
| + | |||
| + | Para lanzar la batería de tests desde la línea de comandos: | ||
| + | |||
| + | < | ||
| + | python -m unittest test_segundo_grado.py | ||
| + | </ | ||
| + | |||
| + | ==== Conversión a números romanos ==== | ||
| + | |||
| + | Esta vez crearemos primero los tests y luego crearemos el código : | ||
| + | |||
| + | <WRAP center round info 60%> | ||
| + | **TDD** (//Test Driven Development// | ||
| + | </ | ||
| + | |||
| + | |||
| + | Fichero '' | ||
| + | |||
| + | <code python> | ||
| + | import unittest | ||
| + | |||
| + | from romanos import roman | ||
| + | |||
| + | class TestRomanos(unittest.TestCase): | ||
| + | |||
| + | def test_1(self): | ||
| + | self.assertEqual(roman(1), | ||
| + | | ||
| + | def test_2(self): | ||
| + | self.assertEqual(roman(2), | ||
| + | | ||
| + | def test_2(self): | ||
| + | self.assertEqual(roman(2), | ||
| + | | ||
| + | def test_3(self): | ||
| + | self.assertEqual(roman(3), | ||
| + | | ||
| + | def test_4(self): | ||
| + | self.assertEqual(roman(4), | ||
| + | | ||
| + | def test_5(self): | ||
| + | self.assertEqual(roman(5), | ||
| + | |||
| + | def test_6(self): | ||
| + | self.assertEqual(roman(6), | ||
| + | | ||
| + | def test_7(self): | ||
| + | self.assertEqual(roman(7), | ||
| + | |||
| + | def test_9(self): | ||
| + | self.assertEqual(roman(9), | ||
| + | | ||
| + | def test_10(self): | ||
| + | self.assertEqual(roman(10), | ||
| + | |||
| + | def test_13(self): | ||
| + | self.assertEqual(roman(13), | ||
| + | | ||
| + | def test_14(self): | ||
| + | self.assertEqual(roman(14), | ||
| + | | ||
| + | def test_17(self): | ||
| + | self.assertEqual(roman(17), | ||
| + | | ||
| + | def test_19(self): | ||
| + | self.assertEqual(roman(19), | ||
| + | | ||
| + | def test_20(self): | ||
| + | self.assertEqual(roman(20), | ||
| + | | ||
| + | def test_27(self): | ||
| + | self.assertEqual(roman(27), | ||
| + | |||
| + | def test_33(self): | ||
| + | self.assertEqual(roman(33), | ||
| + | | ||
| + | def test_40(self): | ||
| + | self.assertEqual(roman(40), | ||
| + | |||
| + | def test_49(self): | ||
| + | self.assertEqual(roman(49), | ||
| + | |||
| + | def test_50(self): | ||
| + | self.assertEqual(roman(50), | ||
| + | |||
| + | def test_62(self): | ||
| + | self.assertEqual(roman(62), | ||
| + | | ||
| + | def test_90(self): | ||
| + | self.assertEqual(roman(90), | ||
| + | | ||
| + | def test_97(self): | ||
| + | self.assertEqual(roman(90), | ||
| + | | ||
| + | def test_100(self): | ||
| + | self.assertEqual(roman(100), | ||
| + | |||
| + | def test_333(self): | ||
| + | self.assertEqual(roman(333), | ||
| + | | ||
| + | def test_400(self): | ||
| + | self.assertEqual(roman(400), | ||
| + | | ||
| + | def test_500(self): | ||
| + | self.assertEqual(roman(500), | ||
| + | | ||
| + | def test_666(self): | ||
| + | self.assertEqual(roman(666), | ||
| + | | ||
| + | def test_900(self): | ||
| + | self.assertEqual(roman(900), | ||
| + | | ||
| + | def test_1000(self): | ||
| + | self.assertEqual(roman(1000), | ||
| + | | ||
| + | def test_1666(self): | ||
| + | self.assertEqual(roman(1666), | ||
| + | | ||
| + | def test_3999(self): | ||
| + | self.assertEqual(roman(3999), | ||
| + | |||
| + | if __name__ == ' | ||
| + | unittest.main() | ||
| + | |||
| + | </ | ||
| + | |||
| + | Creamos el programa '' | ||
| + | |||
| + | <code python> | ||
| + | """ | ||
| + | Romani ite domum! | ||
| + | |||
| + | TDD - Test Driven Development | ||
| + | |||
| + | 1. Escribir un test (que inicialmente falle) | ||
| + | 2. Escribir el código que haga pasar el test | ||
| + | 3. Refactorizar el código: optimización, | ||
| + | (Y vuelta a empezar...) | ||
| + | """ | ||
| + | |||
| + | def roman(n: int) -> str: | ||
| + | |||
| + | cantidades = [ | ||
| + | (1000, " | ||
| + | (90, " | ||
| + | (5, " | ||
| + | ] | ||
| + | |||
| + | conv = "" | ||
| + | | ||
| + | for cant, letras in cantidades: | ||
| + | while n >= cant. | ||
| + | n -= cant | ||
| + | conv += letras | ||
| + | | ||
| + | return conv | ||
| + | </ | ||
| + | |||
| + | Opción con recursividad: | ||
| + | |||
| + | <code python> | ||
| + | def roman2(n: int) -> str: | ||
| + | |||
| + | if n >= 1000: | ||
| + | return " | ||
| + | elif n >= 900: | ||
| + | return " | ||
| + | elif n >= 500: | ||
| + | return " | ||
| + | elif n >= 400: | ||
| + | return " | ||
| + | elif n >= 100: | ||
| + | return " | ||
| + | elif n >= 90: | ||
| + | return " | ||
| + | elif n >= 50: | ||
| + | return " | ||
| + | elif n >= 40: | ||
| + | return " | ||
| + | elif n >= 10: | ||
| + | return " | ||
| + | elif n >= 9: | ||
| + | return " | ||
| + | elif n >= 5: | ||
| + | return " | ||
| + | elif n >= 4: | ||
| + | return " | ||
| + | elif n >= 1: | ||
| + | return " | ||
| + | else: | ||
| + | return "" | ||
| + | </ | ||
| + | |||
| + | * [[https:// | ||
| + | |||
| + | ===== JSON ===== | ||
| + | |||
| + | JSON (// | ||
| + | |||
| + | JSON no son más que objetos (que son equivalentes a los diccionarios de Python) y listas. | ||
| + | |||
| + | Se trata de texto. | ||
| + | |||
| + | * https:// | ||
| + | |||
| + | ==== JSON en Python ==== | ||
| + | |||
| + | Aspecto de un JSON, que lo representamos como string: | ||
| + | |||
| + | <code python> | ||
| + | datos_json = ''' | ||
| + | { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | ] | ||
| + | }, | ||
| + | " | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | ''' | ||
| + | </ | ||
| + | |||
| + | * [[https:// | ||
| + | |||
| + | <code python> | ||
| + | # Biblioteca de Python para el tratamiento de JSON | ||
| + | import json | ||
| + | |||
| + | # Cargamos a partir de un string un objeto JSON/ | ||
| + | datos = json.loads(datos_json) | ||
| + | |||
| + | type(datos) # dict | ||
| + | |||
| + | datos.keys() # dict_keys([' | ||
| + | |||
| + | glossary = datos[' | ||
| + | |||
| + | glossary.keys() # dict_keys([' | ||
| + | |||
| + | paises_capitales = { | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | |||
| + | type(paises_capitales) # dict | ||
| + | |||
| + | # Si queremos pasar de un diccionario a string en formato JSON | ||
| + | json.dumps(paises_capitales) | ||
| + | </ | ||
| + | |||
| + | * [[https:// | ||
| + | |||
| + | Si procesamos un JSON inválido: | ||
| + | |||
| + | <code python> | ||
| + | mal_json = ''' | ||
| + | {" | ||
| + | ''' | ||
| + | |||
| + | try: | ||
| + | json.loads(mal_json) | ||
| + | except json.JSONDecodeError as error: | ||
| + | print(" | ||
| + | </ | ||
| + | |||
| + | |||
| + | disculpa, Jairo, sabes hasta qué día tenemos disponible el acceso al campus virtual? | ||
informatica/programacion/python/cursos/introduccion_programacion_python/ejemplos_practicos.1682581541.txt.gz · Última modificación: por tempwin
