Este curso se centra en cómo la IA generativa puede mejorar la colaboración en el desarrollo de software, facilitando tareas como la prueba y depuración de código, la documentación y la gestión de dependencias. A través de ejemplos prácticos, se exploran las ventajas de utilizar modelos de lenguaje (LLMs) como compañeros de programación.
Facilita la entrega de casos de prueba al equipo de testing.
Documentación
Uso de herramientas de auto-documentación para crear documentación a partir de los comentarios.
Gestión de Dependencias
La IA generativa no solo ayuda a los desarrolladores a mejorar su propio código, sino que también facilita la colaboración y el trabajo en equipo. Al utilizar LLMs, los desarrolladores pueden convertirse en mejores programadores y compañeros de trabajo.
| Beneficio | Descripción |
|---|---|
| Mejora en Pruebas | Facilita la creación y entrega de casos de prueba. |
| Documentación Eficiente | Genera documentación automáticamente a partir de comentarios en el código. |
| Gestión de Dependencias | Ayuda a integrar y gestionar dependencias de manera efectiva. |
Con este curso, los participantes aprenderán a utilizar la IA generativa para optimizar su flujo de trabajo y mejorar la calidad del software que desarrollan.
Las pruebas de software son un paso fundamental en el proceso de desarrollo que garantiza el lanzamiento de productos de alta calidad y que funcionan correctamente, lo que resulta en grandes experiencias para los usuarios. Este documento resume los conceptos clave sobre la importancia de las pruebas de software y su implementación.
El desarrollo de software sin pruebas adecuadas puede llevar a fallos impredecibles, frustración en los usuarios y pérdidas financieras. A lo largo de este curso, se explorarán diferentes tipos de pruebas y cómo implementarlas, incluyendo el uso de modelos de lenguaje (LLM) como aliados en el proceso.
Un caso famoso de fallo de software es el del Mars Climate Orbiter, que en 1998, tras viajar más de 100 millones de kilómetros, falló en alcanzar su altitud orbital debido a un error de conversión de unidades entre equipos que usaban diferentes sistemas de medida (métrico e imperial). Este error resultó en la pérdida de una misión de $200,000,000 y años de descubrimientos científicos.
A lo largo de los siguientes videos, se explorarán los siguientes temas:
Pruebas Funcionales
Implementación de Pruebas con LLM:
Uso de modelos de lenguaje para facilitar la creación de scripts de prueba.
Pruebas Automatizadas:
Estrategias para reducir la carga cognitiva al trabajar con herramientas automatizadas.
Pruebas de Rendimiento:
Evaluación del rendimiento de la aplicación bajo diferentes condiciones y cargas.
Identificación de Vulnerabilidades de Seguridad:
Las pruebas de software son esenciales para el éxito de cualquier proyecto de desarrollo. Familiarizarse con las diferentes técnicas y herramientas disponibles, incluyendo la colaboración con modelos de lenguaje, puede mejorar significativamente la calidad del software y la experiencia del usuario.
¡Vamos al siguiente video y comencemos a explorar las estrategias de prueba!
En este documento se presenta un resumen de un curso sobre cómo utilizar un modelo de lenguaje grande (LLM) para desarrollar estrategias de pruebas en una aplicación web simple construida con Flask. Se exploran conceptos clave, ejemplos de código y estrategias de prueba.
Flask es un marco de trabajo ligero para Python, ideal para crear aplicaciones web. En este curso, se utiliza una aplicación Flask que tiene un único endpoint API: /api/greet/<name>, que recibe un nombre como parámetro y devuelve un mensaje de saludo.
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/api/greet/<name>', methods=['GET'])
def greet(name):
return jsonify(message=f"Hello, {name}!")
if __name__ == '__main__':
app.run()
Si se ejecuta en un entorno compartido como Google Colab, es necesario modificar el código para usar hilos, ya que los notebooks finalizan la ejecución de la celda actual antes de pasar a la siguiente. Esto permite que el servidor API se ejecute en un hilo separado.
Para llamar a la API, se puede utilizar cURL o la biblioteca requests de Python. Asegúrate de usar la dirección IP reportada por Colab si estás ejecutando el código allí.
Una vez que la API está en funcionamiento, se sugiere pausar y pensar en los casos de prueba que se podrían utilizar para verificar su correcto funcionamiento. Algunas preguntas a considerar son: - ¿Qué datos se pueden pasar para comprobar el comportamiento? - ¿Cómo se podría romper la API?
Se recomienda utilizar un LLM como GPT para generar casos de prueba. Al hacerlo, es importante seguir algunas mejores prácticas de prompting: 1. Ser específico: Proporcionar detalles y contexto sobre el problema. 2. Asignar un rol: Pedir al modelo que actúe como un experto en pruebas de software. 3. Interacción: Mantener un diálogo con el modelo para afinar la salida.
Como un experto en pruebas de software que está enseñando a una nueva persona a escribir casos de prueba, ¿puedes analizar este código y proporcionar un conjunto de casos de prueba explicando cada uno?
Al utilizar el prompt anterior, se pueden obtener varios casos de prueba, tales como:
| Caso de Prueba | Descripción | Salida Esperada |
|---|---|---|
| Saludo básico | Probar el saludo básico con un nombre. | JSON: |
| Manejo de codificación URL | Probar con un nombre que contenga espacios (ej. "John Doe"). | JSON: |
| Caracteres especiales | Probar con nombres que contengan caracteres especiales. | JSON: |
| Nombres vacíos | Probar con un nombre vacío. | JSON: |
| Entrada numérica | Probar con un número como entrada. | JSON: |
El uso de LLMs puede ser una herramienta poderosa para generar casos de prueba y mejorar la calidad del software. En el siguiente video, se explorará más a fondo el concepto de pruebas exploratorias y cómo un LLM puede asistir en este proceso.
En este curso, se exploran las pruebas manuales, centrándose en las pruebas exploratorias como una estrategia clave para identificar errores en aplicaciones simples, como un endpoint de Flask. Se discute cómo trabajar con un modelo de lenguaje (LLM) puede facilitar el proceso de prueba y se presentan ejemplos prácticos utilizando una aplicación de lista de tareas en Python.
# Agregar tareas
add_task("Comprar groceries")
add_task("Leer un libro")
# Listar tareas
list_tasks()
# Eliminar una tarea
remove_task("Leer un libro")
list_tasks()
| Problema Identificado | Sugerencia de Mejora |
|---|---|
| Uso de variables globales | Evitar el uso de variables globales. |
| Tipos de retorno inconsistentes | Unificar los tipos de retorno. |
| Duplicación de tareas | Implementar verificación de duplicados. |
| Manejo de tareas vacías | Prohibir la adición de tareas vacías. |
| Seguridad en hilos | Implementar bloqueo de hilos. |
En el siguiente video, se explorará cómo un LLM puede ayudar a formalizar los resultados de las pruebas exploratorias en un conjunto de pruebas funcionales.
Este documento resume los conceptos clave sobre las pruebas funcionales, su importancia en el desarrollo de software y cómo se pueden implementar utilizando herramientas como LLM (Modelos de Lenguaje de Aprendizaje Automático). Se discuten ejemplos prácticos y se enfatiza la necesidad de mantener y actualizar los casos de prueba a medida que evoluciona la aplicación.
Las pruebas funcionales son una extensión de las pruebas exploratorias manuales. Su objetivo es verificar que la funcionalidad de la aplicación cumpla con los requisitos predefinidos. Esto se logra mediante la creación de casos de prueba que aseguran que cada función del código funcione como se espera.
unittest.import unittest
class TestTodoList(unittest.TestCase):
def setUp(self):
self.todo_list = TodoList()
def test_add_task(self):
self.todo_list.add_task("Task 1")
self.assertIn("Task 1", self.todo_list.tasks)
def test_remove_task(self):
self.todo_list.add_task("Task 1")
self.todo_list.remove_task("Task 1")
self.assertNotIn("Task 1", self.todo_list.tasks)
def test_remove_nonexistent_task(self):
result = self.todo_list.remove_task("Nonexistent Task")
self.assertEqual(result, "Task not found")
def test_list_tasks(self):
self.todo_list.add_task("Task 1")
self.assertEqual(self.todo_list.list_tasks(), ["Task 1"])
def test_add_empty_task(self):
result = self.todo_list.add_task("")
self.assertEqual(result, "Task cannot be empty")
Las pruebas funcionales son esenciales para garantizar que las aplicaciones se comporten como se espera. Aunque los LLM son herramientas útiles para generar pruebas, es importante no depender completamente de ellos. La intervención humana sigue siendo crucial para asegurar la calidad del software.
En el siguiente video, se explorará cómo los LLM pueden facilitar las pruebas automatizadas, lo que es fundamental para el mantenimiento de aplicaciones en producción.
| Función de Prueba | Descripción |
|---|---|
test_add_task |
Verifica que una tarea se añade correctamente. |
test_remove_task |
Verifica que una tarea se elimina correctamente. |
test_remove_nonexistent_task |
Verifica el manejo de la eliminación de tareas no existentes. |
test_list_tasks |
Verifica que la lista de tareas se devuelve correctamente. |
test_add_empty_task |
Verifica que no se permite añadir una tarea vacía. |
Este resumen proporciona una visión general de la importancia y la implementación de las pruebas funcionales en el desarrollo de software, así como el papel de los LLM en este proceso.
Este documento resume los conceptos clave sobre las pruebas automatizadas en Python utilizando el marco de trabajo pytest. Se discuten las ventajas de las pruebas automatizadas, cómo implementarlas y se presentan ejemplos prácticos relacionados con una aplicación de lista de tareas.
def test_add_task():
tasks = []
tasks.append("Task 1")
assert tasks == ["Task 1"]
tasks.append("Task 2")
assert tasks == ["Task 1", "Task 2"]
tasks.append("Task 3")
assert tasks == ["Task 1", "Task 2", "Task 3"]
def test_add_empty_task():
with pytest.raises(ValueError):
tasks.append("") # Se espera un error al agregar una tarea vacía
pip install pytest en la terminal.test_ para ejecutar las pruebas.| Ventaja | Descripción |
|---|---|
| Ahorro de tiempo | Realiza tareas repetitivas automáticamente. |
| Reducción de errores humanos | Minimiza la intervención manual. |
| Retroalimentación rápida | Permite detectar problemas en etapas tempranas. |
| Mantenimiento de calidad | Asegura la confiabilidad del software a largo plazo. |
pytest y ejecutar las pruebas.Este resumen proporciona una visión general de las pruebas automatizadas utilizando pytest, destacando su importancia y cómo implementarlas en un proyecto práctico.
Las pruebas de rendimiento son fundamentales para garantizar que las aplicaciones funcionen de manera eficiente en producción y puedan manejar la carga de usuarios esperada. Este documento resume los conceptos clave sobre la medición del tiempo de ejecución y la identificación de cuellos de botella en el rendimiento, utilizando bibliotecas específicas de Python.
Se presenta un código que encuentra números primos en un rango y calcula su suma. A continuación, se mide el tiempo de ejecución y se identifican cuellos de botella.
def is_prime(n):
# Lógica para determinar si n es primo
pass
def sum_of_primes_naive(limit):
# Lógica para sumar números primos hasta el límite
pass
timeit para medir el tiempo de ejecución de la función sum_of_primes_naive.number para evitar tiempos de ejecución excesivos.cProfile para identificar que la función is_prime es el principal cuello de botella.cProfile.def is_prime_optimized(n):
# Lógica optimizada para determinar si n es primo
pass
Las pruebas de rendimiento son un aspecto especializado del desarrollo de software. Al aplicar las mejores prácticas de consulta y proporcionar contexto, se puede mejorar significativamente la eficiencia del código. En el siguiente video, se explorará la importancia de las pruebas de seguridad.
| Herramienta | Descripción |
|---|---|
timeit |
Mide el tiempo de ejecución de fragmentos de código. |
cProfile |
Analiza el tiempo en cada función para identificar cuellos de botella. |
timeit para medir el tiempo de ejecución.cProfile para identificar cuellos de botella.Este documento proporciona una guía básica sobre cómo realizar pruebas de rendimiento en aplicaciones utilizando Python, destacando la importancia de la medición y la optimización del código.
En este módulo se explora el concepto de pruebas de seguridad en aplicaciones, destacando la importancia de entender las vulnerabilidades de seguridad y cómo los modelos de lenguaje (LLM) pueden ser útiles, pero también limitados en este contexto.
Las pruebas de seguridad son cruciales para proteger aplicaciones, especialmente aquellas que exponen activos a través de APIs en Internet. La seguridad es un campo en constante evolución, donde los atacantes y hackers están siempre buscando nuevas formas de explotar vulnerabilidades.
Los LLM pueden ser útiles para: - Iniciar conversaciones sobre seguridad en equipos de trabajo. - Proporcionar información general sobre prácticas de seguridad.
Se presenta un ejemplo de una aplicación simple que utiliza un API REST para la gestión de usuarios. La estructura de un usuario en la base de datos incluye:
- id
- username
- password
Un ejemplo de cómo se podría implementar un endpoint para obtener detalles de un usuario:
@app.route('/user/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = query_database(user_id) # Consulta a la base de datos
return jsonify(user) # Retorna los detalles en formato JSON
Una de las vulnerabilidades más comunes es la inyección SQL. Esto ocurre cuando un atacante puede manipular una consulta SQL a través de parámetros de entrada. Por ejemplo, si un endpoint acepta un ID de usuario, un atacante podría inyectar código SQL malicioso.
Si el código permite un input como user_id=1, un atacante podría enviar algo como:
1; DROP TABLE users; --
Esto podría resultar en la eliminación de la tabla de usuarios.
Se sugiere a los participantes que utilicen el cuaderno proporcionado en los materiales del curso para experimentar con la aplicación y tratar de identificar vulnerabilidades de inyección SQL.
Las pruebas de seguridad son fundamentales en el desarrollo de aplicaciones. Aunque los LLM pueden ser herramientas útiles, es crucial tener un entendimiento profundo de la seguridad y contar con la ayuda de expertos en el área.
Este documento resume un video que presenta una aplicación Flask y su análisis en busca de problemas de seguridad. Se explican los conceptos básicos de la aplicación, la configuración de la base de datos y las operaciones CRUD (Crear, Leer, Actualizar, Eliminar) que se pueden realizar sobre los usuarios.
Para comenzar, es necesario instalar SQLAlchemy, que se utilizará para manejar la base de datos.
pip install SQLAlchemy
La aplicación Flask se configura para utilizar una base de datos SQLite. La URI de la base de datos se establece de la siguiente manera:
DATABASE_URI = 'sqlite:///users.db'
Se define una clase User que representa a los usuarios en la base de datos. Esta clase incluye los siguientes atributos:
id: Identificador único del usuario.username: Nombre de usuario.password: Contraseña del usuario.La aplicación define varias rutas para interactuar con los usuarios. A continuación se detallan las operaciones disponibles:
| Método HTTP | Ruta | Descripción |
|---|---|---|
| GET | /users | Devuelve todos los usuarios en formato JSON. |
| GET | /user/ |
Devuelve el usuario con el ID especificado. |
| POST | /user | Agrega un nuevo usuario con username y password. |
| PUT | /user/ |
Actualiza el username y password del usuario. |
| DELETE | /user/ |
Elimina el usuario con el ID especificado. |
Listar Usuarios: Al realizar una solicitud GET a /users, se obtendrá una lista de todos los usuarios. Inicialmente, estará vacía.
Buscar Usuario: Al realizar una solicitud GET a /user/1, se buscará el usuario con ID 1. Si no existe, se devolverá un mensaje de error 404.
Agregar Usuario: Para agregar un nuevo usuario, se realiza una solicitud POST a /user con el siguiente JSON:
json
{
"username": "test_user",
"password": "secure_password"
}
Si se agrega correctamente, se recibirá un mensaje de éxito.
Actualizar Usuario: Para actualizar la contraseña de un usuario, se realiza una solicitud PUT a /user/1 con el nuevo username y password.
Eliminar Usuario: Para eliminar un usuario, se realiza una solicitud DELETE a /user/1. Se recibirá un mensaje de éxito si la operación se completa.
Este video proporciona una introducción a la creación de una aplicación Flask básica con operaciones CRUD. Se recomienda revisar el código de la aplicación en el laboratorio no calificado y continuar con el siguiente video para estrategias específicas de análisis de código.
En este módulo, se exploran las mejores prácticas para identificar y mitigar vulnerabilidades de seguridad en el código utilizando modelos de lenguaje (LLM). Se enfatiza la importancia de realizar pruebas de seguridad de manera continua y colaborativa, involucrando a expertos en seguridad y utilizando herramientas adecuadas.
Generar casos de prueba para las vulnerabilidades detectadas.
Ejemplo de Vulnerabilidades:
Acceso directo a registros de usuarios: Exposición de datos sensibles.
Configuración del Entorno:
Este resumen proporciona una guía clara sobre cómo abordar las pruebas de seguridad en el desarrollo de software, destacando la importancia de la colaboración y el uso de herramientas avanzadas.