0:00:06.640,0:00:12.400 Así pues, en esta charla voy a contarles la historia que hay detrás de SQLancer, 0:00:12.400,0:00:16.640 una herramienta que hemos diseñado y desarrollado para probar automáticamente sistemas de gestión de bases de datos. 0:00:17.520,0:00:22.400 Ahora asumo que muchos de ustedes no están trabajando directamente en el desarrollo de sistemas de gestión de bases de datos, 0:00:22.400,0:00:27.040 por lo que me centraré en las ideas generales que podrían 0:00:27.040,0:00:31.840 aplicar en las pruebas de su proyecto. Para asegurarnos de que todos estamos en 0:00:31.840,0:00:37.760 la misma página, en nuestro trabajo queríamos probar sistemas de gestión de bases de datos que esperan consultas 0:00:37.760,0:00:43.760 o sentencias escritas en el lenguaje de consulta estructurado o, para abreviar, SQL. Como tal vez la mayoría de 0:00:43.760,0:00:49.040 ustedes sepa, podemos utilizar este lenguaje para crear tablas, insertar datos en ellas y, a continuación, 0:00:49.040,0:00:54.880 recuperar datos mediante una sentencia select. Ahora bien, en las charlas anteriores ya hemos oído hablar 0:00:54.880,0:01:00.960 un poco de las pruebas, así que ¿cómo podemos escribir casos de prueba que puedan probar estos sistemas? 0:01:03.120,0:01:08.480 Bueno, un enfoque sería simplemente escribirlos en SQL. Podríamos, por ejemplo, especificar el caso de prueba, 0:01:08.480,0:01:14.000 como aquí tomado de la prueba de MySQL, y luego en un archivo separado especificar 0:01:14.000,0:01:20.480 la salida esperada. Y aunque hay algunos frameworks que hacen este proceso un poco más fácil, 0:01:20.480,0:01:25.680 yo diría que sigue siendo siempre un reto y consume mucho tiempo escribir casos de prueba manuales, 0:01:25.680,0:01:30.400 sobre todo teniendo en cuenta para los sistemas tan complejos donde necesitamos una enorme cantidad de conjuntos de pruebas. 0:01:31.600,0:01:37.200 Así que en nuestro trabajo nos preguntamos, ¿podemos automatizar el proceso de pruebas? Y esto nos lleva a dos 0:01:37.200,0:01:42.880 retos. En primer lugar, si queremos tener un enfoque de pruebas automatizado, necesitamos un caso de prueba, 0:01:42.880,0:01:47.280 y en nuestro caso esto significa que necesitamos generar una base de datos y una consulta que luego podamos 0:01:47.280,0:01:53.520 validar. Así que buscando en lo que ya existe, podemos encontrar herramientas como por ejemplo 0:01:53.520,0:02:00.080 SQLsmith. SQLsmith es una herramienta de generación de consultas eficaz y ampliamente utilizada que muta 0:02:00.080,0:02:06.000 y genera sentencias SQL complejas que pueden causar, por ejemplo, un fallo en el sistema de base de datos 0:02:06.000,0:02:12.400 que los desarrolladores pueden solucionar. Así que yo diría que esto ya es un reto resuelto, por lo que podemos utilizar 0:02:12.400,0:02:16.320 este enfoque de generación aleatoria u otro para generar los casos de prueba. 0:02:18.160,0:02:23.760 Ahora bien, lo que seguía siendo un reto abierto es el llamado problema del oráculo de prueba, digamos que queremos 0:02:23.760,0:02:30.240 validar el resultado de la consulta. Entonces, ¿qué es un oráculo de pruebas? Un oráculo de prueba es básicamente el mecanismo 0:02:30.240,0:02:35.360 que determina si una prueba ha pasado o ha fallado, y para las pruebas de regresión para escribir 0:02:35.360,0:02:41.120 casos de prueba manuales, nosotros típicamente como desarrolladores o desarrolladoras somos - o proporcionamos el oráculo de prueba. 0:02:42.240,0:02:46.480 Pero esto es a menudo difícil, incluso para los casos de prueba escritos manualmente, y quiero ilustrar 0:02:46.480,0:02:51.360 esto basado en un ejemplo concreto. Puedes ver aquí un caso de prueba que realmente nos permitió 0:02:51.360,0:02:58.000 encontrar y reportar un error en MySQL. Puedes ver aquí que tenemos dos tablas t0 y t1, 0:02:58.000,0:03:03.040 cada una de las cuales contiene un valor de punto flotante, concretamente un cero positivo y un cero negativo. 0:03:03.600,0:03:08.240 Y luego instruimos a MySQL para que obtenga el producto cruzado de todos los registros de estas dos tablas 0:03:08.240,0:03:12.320 donde la columna se evalúa con el mismo valor. Ahora, ¿cuál es la salida esperada aquí? 0:03:15.520,0:03:20.160 Yo diría que es discutible si el predicado aquí debería evaluarse como verdadero o falso 0:03:20.880,0:03:25.360 porque podríamos, por ejemplo, mirar la representación binaria de estos dos números de punto flotante 0:03:25.360,0:03:29.520 para darnos cuenta de que el bit de signo difiere. Y en base a esto tendría sentido que el 0:03:29.520,0:03:35.600 operador de igualdad evaluara a falso y MySQL para este caso devolvería un resultado vacío. 0:03:37.520,0:03:43.360 Pero la mayoría de los lenguajes de programación como Java, C, etc., definen la semántica de que 0:03:43.360,0:03:50.480 este operador de igualdad debe evaluarse como verdadero para - para estos valores. Y en este caso MySQL 0:03:50.480,0:03:57.360 obtendría una fila. Así que en este punto de una charla tienes que confiar en mí, en realidad se espera que MySQL obtenga 0:03:57.360,0:04:04.000 el registro. Pero cuando probamos la última versión, todavía no lo hizo. Informamos 0:04:04.000,0:04:09.280 de esto como un error a los desarrolladores que luego lo arreglaron para la próxima versión de MySQL. Pero el 0:04:09.280,0:04:15.920 punto aquí es que pudimos encontrar este error sin tener una idea de si un predicado debe evaluarse 0:04:15.920,0:04:20.320 como verdadero o no y si cualquier resultado o cualquier registro debe ser obtenido. 0:04:21.280,0:04:27.920 Básicamente teníamos este oráculo de prueba que nos decía que el resultado devuelto era correcto. 0:04:27.920,0:04:31.760 Ahora hemos desarrollado un par de oráculos de prueba, el que voy a presentar hoy 0:04:31.760,0:04:37.840 se denomina partición lógica o TLB corto. Y si tuviera que explicar el enfoque en media frase 0:04:37.840,0:04:43.040 diría básicamente que la idea es probar el sistema de gestión de bases de datos contra sí mismo. 0:04:44.640,0:04:50.000 La idea es bastante generosa y quiero explicarla basándome en una analogía. Si alguna vez nos reunimos en 0:04:50.000,0:04:53.920 persona es muy probable que sea en la cafetería porque me gusta beber 0:04:53.920,0:05:01.120 mucho café. Y supongamos también que hay un bol con frutas que contiene mandarinas y 0:05:01.120,0:05:07.520 también clementinas. La verdad es que se me da muy mal distinguir estos cítricos, 0:05:07.520,0:05:12.160 todos me parecen iguales, así que esto es lo que te digo para empezar una conversación. 0:05:12.960,0:05:17.680 Y es posible que respondas que puedes distinguir claramente la diferencia. Así que te reto 0:05:17.680,0:05:23.440 a que me lo demuestres, pero ¿cómo puedo poner a prueba tu entendimiento de las mandarinas frente a las clementinas sin tener 0:05:23.440,0:05:30.480 yo mismo este entendimiento? Bueno, la estrategia que aplicaría sería la siguiente: primero 0:05:30.480,0:05:33.760 te pediría que por favor me trajeras todas las clementinas y tú irías a buscar 0:05:33.760,0:05:38.480 quizás dos de las frutas. Luego las pondría de nuevo en el recipiente, 0:05:38.480,0:05:42.800 las mezclaría y luego te pediría que me trajeras todos los alimentos que no sean clementinas. 0:05:43.840,0:05:48.320 Traerías la manzana que podría reconocer, junto con las otras frutas de aspecto anaranjado. 0:05:49.520,0:05:53.360 Y creo que ya algunos de ustedes ven a dónde va esto porque primero me trajiste dos frutas 0:05:54.240,0:05:59.440 y luego me trajiste cuatro frutas, así que en total seis frutas, pero sólo hay cinco frutas 0:05:59.440,0:06:05.840 en el tazón, lo que significa que probablemente clasificaste una fruta como mandarina y clementina. 0:06:07.040,0:06:11.120 Entonces, la idea de alto nivel aquí es que cada objeto en el universo y también en el bol 0:06:11.120,0:06:15.840 es una clementina o no y usamos esta idea para básicamente dividir todos los 0:06:16.560,0:06:22.320 objetos en el bol. Por supuesto, siempre se puede decir - siempre se puede clasificar consistentemente 0:06:22.320,0:06:27.440 mandarinas como clementinas y al revés, lo que significa que no podemos detectar todos 0:06:27.440,0:06:33.840 los errores, pero tampoco podemos probar - casos de prueba, por lo que esta es una limitación con la que tenemos que vivir. 0:06:35.200,0:06:42.480 ¿Cómo aplicamos ahora esto a SQL? Ahora tenemos cualquier tipo de predicado dado P y una fila R en lugar de 0:06:42.480,0:06:47.840 una fruta, pero exactamente uno de los siguientes debe mantener el predicado evaluado a verdadero, 0:06:48.400,0:06:51.120 no el predicado o es el verdadero lo que significa que se evalúa a falso, 0:06:51.760,0:06:56.560 y luego, ya que en SQL también tenemos que lidiar con los valores nulos, tenemos que lidiar con el caso en que 0:06:56.560,0:07:03.040 P podría evaluar a null. Y basándonos en esto, ahora podemos tomar cualquier tipo de datos en nuestra tabla - cualquier tipo 0:07:03.040,0:07:06.720 de resultado intermedio - y dividirlo en tres partes: entonces hacemos las del predicado 0:07:06.720,0:07:10.920 en las que es verdadero, aquellas en las que se evalúa como falso, y aquellas en las que se evalúa como nulo. 0:07:11.760,0:07:16.160 ¿Cómo nos permitió ahora detectar el error del ejemplo motivador? 0:07:16.160,0:07:22.080 Bueno, primero generamos esta consulta que básicamente corresponde a contar el número de 0:07:23.040,0:07:26.880 frutas en el recipiente. Así que simplemente buscamos el producto cruzado de todos los valores de estas dos tablas. 0:07:27.680,0:07:34.720 Y ahí MySQL devolvió un único registro. Luego generamos estas tres consultas más complejas 0:07:34.720,0:07:39.120 basadas en este predicado aleatorio P. Puedes ver aquí que tenemos la versión no negada, la 0:07:39.120,0:07:44.640 versión negada y esta versión nula. En general, esperamos que esto debería calcular el mismo resultado. 0:07:45.760,0:07:51.680 Sin embargo, MySQL devolvió aquí un conjunto de resultados vacío, lo que nos permitió encontrar e informar del error. 0:07:53.520,0:07:56.880 La técnica es en realidad bastante versátil en el sentido de que podemos probar varios 0:07:56.880,0:08:00.240 tipos diferentes de características SQL, aquí sólo se centra en las cláusulas where. 0:08:02.000,0:08:06.960 Así que básicamente teníamos este enfoque de generación aleatoria para abordar este problema de generación de casos de prueba 0:08:06.960,0:08:14.240 y ahora proponemos el particionamiento lógico ternario para abordar este problema de oráculo de prueba. 0:08:15.680,0:08:20.800 ¿La siguiente pregunta natural es si una técnica tan sencilla puede ser eficaz? Pues bien, he utilizado la 0:08:20.800,0:08:28.160 respuesta SQL TLB como uno de estos enfoques que propusimos para encontrar más de 450 errores únicos y previamente 0:08:28.160,0:08:32.400 desconocidos en los sistemas de gestión de bases de datos de Baidu de los que todos han oído hablar o conocen. 0:08:34.560,0:08:38.320 ¿Y qué deberías sacar de esta charla? Bueno, aunque la técnica específica de 0:08:38.320,0:08:43.440 partición de datos funciona principalmente para los sistemas orientados a datos, se basa en realidad en una 0:08:43.440,0:08:52.560 técnica más genérica, más general. Es decir, si miramos esto desde un nivel abstracto, 0:08:52.560,0:08:57.360 básicamente podemos darnos cuenta de que teníamos un caso de prueba que ejecutamos para obtener un resultado 0:08:58.240,0:09:03.120 y en base a esto derivamos un nuevo caso de prueba para el que podríamos proporcionar un oráculo de prueba. 0:09:04.080,0:09:11.760 Y esto hace la prueba metamórfica. Ahora, lo que puedes hacer es, por supuesto, intentar idear 0:09:11.760,0:09:16.960 una técnica de pruebas metamórficas por ti mismo, pero una alternativa también sería comprobar si 0:09:16.960,0:09:22.560 hay algún enfoque ya existente, por ejemplo, buscando en Google Scholar. 0:09:25.360,0:09:28.000 Y con eso, voy a resumir. Las conclusiones 0:09:28.720,0:09:32.880 son que escribir manualmente los casos de prueba requiere mucho tiempo y un conocimiento detallado del dominio, 0:09:32.880,0:09:36.160 y es posible que te enfrentes a un problema similar en tu trabajo. 0:09:37.040,0:09:43.120 Así que lo que proponemos es combinar la generación aleatoria de casos de prueba con las pruebas metamórficas, que han 0:09:43.120,0:09:49.840 resultado ser un complemento eficaz de los casos de prueba escritos manualmente. Con esto, gracias por escuchar.