Prueba de valores de límite superior e inferior en Python
Funcionalidad de código
El siguiente código prueba si los valores que un usuario especifica para un límite inferior y un límite superior en dos propiedades:
- El límite inferior es más pequeño que el límite superior.
- Los valores son mayores que 0 (positivo).
Dado que primero verifica si el límite inferior es más pequeño que el límite superior, verifica implícitamente que el límite superior es mayor que 0, si prueba si el límite inferior es mayor que 0. Por lo tanto, mi consideración es: puedo hacer que el código sea más compact omitiendo la comprobación de "es el límite superior mayor que 0".
Código
# Object getting labels
class Get_labels:
def __init__(self,lower_bound,upper_bound,configuration_name):
self.lower_bound = lower_bound
self.upper_bound = upper_bound
self.configuration_name = configuration_name
self.check_threshold_validity()
# Verifies if the chosen thresholds are valid values.
def check_threshold_validity(self):
if self.lower_bound>=self.upper_bound:
raise Exception(f'Sorry, the lower threshold={self.lower_bound} should be smaller than the upper bound={self.upper_bound} for configuration={self.configuration_name}')
# checks if lower bound (and implicitly upper bound) are above zero
if self.lower_bound<=0:
raise Exception(f'Sorry, the lower threshold={self.lower_bound} should be larger than 0 for configuration={self.configuration_name}')
if __name__ == '__main__':
get_labels = Get_labels(-1,25,"first")
Elección de diseño
Sin embargo, si se modifica el código, es posible que no sea obvio que el límite superior también debe comprobarse porque se hace implícitamente. Eso podría dar como resultado que el caso de borde con un límite superior por debajo de cero no se detecte después de las modificaciones. Por lo tanto, para evitar este escenario, puedo implementar dos pruebas unitarias que verifiquen si se genera un error para:
- El límite inferior negativo, límite superior negativo
- El límite inferior cero, el límite superior negativo
- El límite inferior positivo, el límite superior negativo
Pregunta
¿Se recomienda incluir la verificación explícita en el código principal de todos modos, aunque se haya probado en las pruebas unitarias?
Respuestas
Excepto en circunstancias inusuales, las clases son cosas o entidades, de ahí el término objetos , mientras que las funciones o métodos son acciones u operaciones. Quieres nombrarlos en consecuencia. Por esa razón, Get_labelsme parece una clase con un nombre extraño. Según lo que nos ha mostrado, podría sugerir el nombre Boundscomo alternativa. Un beneficio adicional de ese nombre es que le permite acortar los nombres de los atributos sin perder su significado.
Un método separado para verificar la validez básica de los límites me parece una ingeniería excesiva, a menos que la lógica de verificación se vuelva mucho más compleja o que se use en otra parte del código. Así que __init__()en este caso solo haría una validación simple .
Evite la tentación de usar mensajes conversadores o detallados en su código. No le ayudará a usted ni a sus usuarios a largo plazo, al menos esa es mi experiencia. Mantenga las cosas directas y rigurosamente concisas. De hecho, a menudo es beneficioso mantener los mensajes muy técnicos en lugar de naturales en su orientación estilística. Lo que quiero decir con eso es que en lugar de describir el problema de la manera en que se podría verbalmente a un humano ("El límite inferior, que era 1000, debe ser menor que el límite superior, que es 125"), a menudo es mejor describir el problema de una manera formulista, esquemática, similar a una computadora. Entre otras cosas, ese enfoque le permite adoptar un formato convencional para todos los mensajes de error en una aplicación. El formato del mensaje de error que se muestra en la reescritura a continuación podría describirse genéricamente como PROBLEM: SELF. Un enfoque coherente hace que sea más fácil escribir código de validación en primer lugar y mantenerlo a lo largo del tiempo. La coherencia también transmite profesionalismo a los usuarios.
En ese sentido, a menudo puede simplificar la creación de dichos mensajes de validación definiendo primero __repr__()para su clase, como se ilustra a continuación.
Para las validaciones que tiene hasta ahora, a ValueErrores más adecuado que criar a un general Exception. Además, podría considerar verificar otros tipos de errores: por ejemplo, ¿los límites están restringidos solo a números enteros?
Si comprueba eso, plantee un TypeError.
Finalmente, un fino punto estilístico y ciertamente subjetivo. A continuación se muestra un seguimiento de la pila de su código tal como está escrito. Vemos el mensaje detallado dos veces, primero como una cadena f, y luego con los parámetros completados. ¿Qué hay de malo en eso? Nada serio, pero pesado, tedioso, incluso sin cierta elegancia. Como mínimo, se podría decir que la repetición del mensaje detallado distrae levemente al usuario, lo que supone un incremento adicional de la carga visual o cognitiva sobre el usuario para descubrir qué está pasando. Compare eso con el seguimiento de la pila del código revisado.
# ORIGINAL.
Traceback (most recent call last):
File "bounds.py", line 19, in <module>
get_labels = Get_labels(-1,25,"first")
File "bounds.py", line 7, in __init__
self.check_threshold_validity()
File "bounds.py", line 17, in check_threshold_validity
raise Exception(f'Sorry, the lower threshold={self.lower_bound} should be larger than 0 for configuration={self.configuration_name}')
Exception: Sorry, the lower threshold=-1 should be larger than 0 for configuration=first
# REVISED.
Traceback (most recent call last):
File "bounds.py", line 72, in <module>
b1 = Bounds(1000, 125, 'first')
File "bounds.py", line 67, in __init__
raise Exception(msg)
Exception: Upper bound must be greater than lower: Bounds(1000, 125, first)
Código con algunas posibles ediciones para que las considere:
class Bounds:
def __init__(self, lower, upper, name):
self.lower = lower
self.upper = upper
self.name = name
if lower <= 0 or upper <= 0:
msg = f'Bounds must be positive: {self}'
raise ValueError(msg)
if upper <= lower:
msg = f'Upper bound must be greater than lower: {self}'
raise ValueError(msg)
def __repr__(self):
return f'Bounds({self.lower}, {self.upper}, {self.name!r})'