UnitTests ofrece una función de prueba unitaria que puede ser utilizada por otros scripts que utilicen require . Consulte Wikipedia:Lua#Unit_testing para obtener más detalles. El siguiente es un ejemplo de Module:Example/testcases :
-- Pruebas unitarias para [[Module:Example]]. Haga clic en la página de discusión para ejecutar las pruebas. local p = require ( 'Module:UnitTests' )función p : test_hello () self : preprocess_equals ( '¡Hola mundo!' , '¡Hola mundo!' ) finvolver p
La página de discusión Módulo discusión:Example/testcases lo ejecuta con {{#invoke: Example/testcases | run_tests}}
. Los métodos de prueba como test_hello arriba deben comenzar con " test ".
run_tests
:Ejecuta todas las pruebas. Normalmente se utiliza en la página de discusión de pruebas unitarias.{{ #invoke : Ejemplo/casos de prueba | ejecutar_pruebas }}
differs_at
se especifica, se agregará una columna que muestra la posición del primer carácter donde los resultados esperados y reales difieren.{{ #invoke : Ejemplo/casos de prueba | ejecutar_pruebas | difiere_en = 1 }}
highlight
se especifica, las pruebas fallidas se resaltarán para que sea más fácil detectarlas. También está disponible un script de usuario que mueve las pruebas fallidas a la parte superior .{{ #invoke : Ejemplo/casos de prueba | ejecutar_pruebas | resaltar = 1 }}
live_sandbox
se especifica, el encabezado mostrará las columnas "Prueba", "En vivo", "Sandbox" y "Esperado". Esto es obligatorio cuando se utiliza el preprocess_equals_sandbox_many
método.preprocess_equals(text, expected, options)
: Proporciona un fragmento de wikitexto para preprocesar y un valor resultante esperado. Los scripts y las plantillas se pueden invocar de la misma manera que en una página.self : preprocess_equals ( '{{#invoke:Example | hola}}' , '¡Hola, mundo!' , { nowiki = 1 })
preprocess_equals_many(prefix, suffix, cases, options)
: Realiza una serie de llamadas preprocess_equals() en un conjunto de pares dados. Agrega automáticamente el prefijo y el sufijo dados a cada texto.yo mismo : preprocess_equals_many ( '{{#invoke:Example | hola_a |' , '}}' , { { 'Juan' , '¡Hola, Juan!' }, { 'Juana' , '¡Hola, Jane!' }, }, { nowiki = 1 })
preprocess_equals_preprocess(text, expected, options)
: Proporciona dos fragmentos de wikitexto para preprocesar y determina si producen el mismo valor. Resulta útil para comparar scripts con plantillas existentes.yo mismo : preprocess_equals_preprocess ( '{{#invoke:Example | hola}}' , '{{Hola}}' , { nowiki = 1 })
preprocess_equals_preprocess_many(prefix1, suffix1, prefix2, suffix2, cases, options)
: Realiza una serie de llamadas preprocess_equals_preprocess() en un conjunto de pares dados. El prefijo o sufijo suministrado para ambos argumentos se agrega automáticamente. Si en algún caso no se especifica la segunda parte, se utilizará la primera.yo mismo : preprocess_equals_preprocess_many ( '{{#invoke:ConvertNumeric | numeral_to_english|' , '}}' , '{{spellnum' , '}}' , { { '2' }, -- equivalente a {'2','2'}, { '-2' , '-2.0' }, }, { nowiki = 1 })
preprocess_equals_sandbox_many(module, function, cases, options)
: Realiza una serie de llamadas preprocess_equals_compare() en un conjunto de pares dados. La prueba compara la versión activa del módulo con la versión /sandbox y con un resultado esperado. Asegúrese de que se especifique live_sandbox o puede haber algunos errores en la salida.yo mismo : preprocess_equals_sandbox_many ( '{{#invoke:Example' , 'hello_to' , { { 'John' , '¡Hola, John!' }, { 'Jane' , '¡Hola, Jane!' }, }, { nowiki = 1 })
equals(name, actual, expected, options)
: Proporciona un valor calculado y el valor esperado, y verifica si son iguales según el operador ==. Útil para probar módulos que están diseñados para ser utilizados por otros módulos en lugar de usar #invoke.self : equals ( 'Suma simple' , 2 + 2 , 4 , { nowiki = 1 })
equals_deep(name, actual, expected, options)
:Al igual que equals, pero maneja las tablas haciendo una comparación profunda. Ninguno de los valores debe contener referencias circulares, ya que no son manejadas por la implementación actual y pueden resultar en un bucle infinito.self : equals_deep ( 'Comparación de tablas' , createRange ( 1 , 3 ), { 1 , 2 , 3 }, { nowiki = 1 })
Estas son las opciones válidas que se pueden pasar a los parámetros de opciones de las funciones de prueba enumeradas anteriormente.
Al habilitar esta opción, el texto de salida se envuelve en <nowiki>...</nowiki>
etiquetas para evitar que se represente (por ejemplo, <span>[[Example|Page]]</span> en lugar de Page ).
Al habilitar esta opción, se mostrará el texto de salida tanto en el modo renderizado como en el modo nowiki para permitir una comparación visual y del texto sin formato.
Al habilitar esta opción, se corrigen los identificadores en los marcadores de tira <templatestyles>...</templatestyles>
que se producen cuando se procesan para evitar que las pruebas fallen incorrectamente.
Al habilitar esta opción, se corrigen los identificadores en todos los marcadores de tira producidos cuando se procesan para evitar que las pruebas fallen incorrectamente.
Una función opcional que cambia la forma en que se muestran los resultados de las pruebas. Esto no afecta el proceso de comparación.
-- UnitTester proporciona pruebas unitarias para otros scripts de Lua. Para más detalles, consulte [[Wikipedia:Lua#Unit_testing]]. -- Para la documentación del usuario, consulte la página de discusión. local UnitTester = {} local frame , tick , cross , should_highlight local result_table_header = " {|class= \" wikitable unit-tests-result \"\n |+ %s \n ! !! Texto !! Esperado !! Real" local result_table_live_sandbox_header = "{|class= \" wikitable unit-tests-result \"\n |+ %s \n ! !! Prueba !! En vivo !! Sandbox !! Esperado" local result_table = { n = 0 } local result_table_mt = { insert = function ( self , ...) local n = self . n para i = 1 , seleccionar ( '#' , ...) hacer local val = seleccionar ( i , ...) si val ~= nulo entonces n = n + 1 self [ n ] = val fin fin self.n = n fin , insertar_formato = función ( self , ...) self : insertar ( cadena.formato ( ... )) fin , concat = tabla.concat } tabla_resultados_mt .__ índice = tabla_resultados_mt establecermetatable ( tabla_resultados , tabla_resultados_mt ) local núm_errores = 0 local núm_ejecuciones = 0 local función primera_diferencia ( s1 , s2 ) s1 , s2 = tostring ( s1 ), tostring ( s2 ) si s1 == s2 entonces devuelve '' fin local max = math.min ( # s1 , # s2 ) para i = 1 , max hacer si s1 : sub ( i , i ) ~= s2 : sub ( i , i ) entonces devuelve i fin fin devuelve max + 1 fin de la función local return_varargs (...) devuelve ... fin de la función UnitTester : calculate_output ( texto , esperado , actual , opciones ) - Configurar algunas variables para facilitar num_runs = num_runs + 1 local options = opciones o {} - Corrija cualquier marcador de franja si se le solicita para evitar fallas incorrectas local comparative_expected = esperado local comparative_actual = actual si opciones . templatestyles entonces patrón local = '( \127 [^ \127 ]*UNIQ%-%-templatestyles%-)(%x+)(%-QINU[^ \127 ]* \127 )' local _ , expected_stripmarker_id = comparative_expected : match ( patrón ) -- cuando la representación del módulo tiene marcadores de tira de templatestyles, usa el ID de expected para evitar una falla de prueba falsa if expected_stripmarker_id then comparative_actual = comparative_actual : gsub ( patrón , '%1' .. expected_stripmarker_id .. '%3' ) -- reemplaza el id actual con el id esperado; ignora la segunda captura en el patrón comparative_expected = comparative_expected : gsub ( patrón , '%1' .. expected_stripmarker_id .. '%3' ) -- tener en cuenta otros marcadores de tira al final si hay opciones . stripmarker entonces patrón local = '( \127 [^ \127 ]*UNIQ%-%-%l+%-)(%x+)(%-%-?QINU[^ \127 ]* \127 )' local _ , expected_stripmarker_id = comparative_expected : match ( patrón ) si expected_stripmarker_id entonces comparative_actual = comparative_actual : gsub ( patrón , '%1' .. expected_stripmarker_id .. ' %3' ) comparative_expected = comparative_expected : gsub ( patrón , '%1' .. expected_stripmarker_id .. '%3' ) fin fin -- Realizar la comparación local success = comparative_actual == comparative_expected si no success entonces num_failures = num_failures + 1 fin -- Ordenar el wikitexto para mostrar los resultados si options . combinado entonces - Necesitamos 2 filas disponibles para las columnas esperadas y reales - La superior se analiza, la inferior no se analiza local difference_at = self . difference_at and ( ' \n | rowspan=2|' .. first_difference ( comparison_expected , comparison_actual )) o '' - Copias locales de tick/cross para permitir resaltar local highlight = ( should_highlight and not success and 'style="background:#fc0;" ' ) o '' result_table : insert ( - Iniciar salida '| ' , highlight , 'rowspan=2|' , success y tick o cross , - Tick/Cross (2 filas) ' \n | rowspan=2|' , mw . text . nowiki ( texto ), ' \n | ' , -- Texto usado para la prueba (2 filas) esperado , ' \n | ' , actual , -- Las salidas analizadas (en la 1.ª fila) difference_at , ' \n |- \n | ' , -- Donde había alguna diferencia relevante (2 filas) mw . texto . nowiki ( esperado ), ' \n | ' , mw . texto . nowiki ( actual ), -- Las salidas no analizadas (en la 2.ª fila) ' \n |- \n ' -- Fin de la salida ) else -- Mostrar normalmente con la opción que se prefirió (nowiki/analizado) local difference_at = self . difference_at and ( ' \n | ' .. first_difference ( comparison_expected , comparison_actual )) o '' local formatting = options . nowiki and mw . texto . nowiki o return_varargs local highlight = ( should_highlight y no success y 'style="background:#fc0;"|' ) o '' result_table : insert ( -- Iniciar salida '| ' , resaltar , success y marcar o cruzar , -- Marcar/Cruzar ' \n | ' , mw . text . nowiki ( text ), ' \n | ' , -- Texto usado para la prueba formatting ( esperado ), ' \n | ' , formatting ( real ), -- Las salidas formateadas difieren_en ,-- Donde haya alguna diferencia relevante ' \n |- \n ' -- Salida final ) fin fin función UnitTester : preprocess_equals ( texto , esperado , opciones ) local actual = marco : preprocess ( texto ) self : calculate_output ( texto , esperado , actual , opciones ) fin función UnitTester : preprocess_equals_many ( prefijo , sufijo , casos , opciones ) para _ , caso en ipairs ( casos ) hacer self : preprocess_equals ( prefijo .. caso [ 1 ] .. sufijo , caso [ 2 ] , opciones ) fin fin función UnitTester : preprocess_equals_preprocess ( texto1 , texto2 , opciones ) local actual = marco : preprocess ( texto1 ) local esperado = marco : preprocess ( texto2 ) self : calculate_output ( texto1 , esperado , actual , opciones ) fin función UnitTester : preprocess_equals_compare ( en vivo , sandbox , esperado , opciones ) live_text local = marco : preprocesar ( en vivo ) sandbox_text local = marco : preprocesar ( sandbox ) highlight_live local = falso highlight_sandbox local = falso num_runs = num_runs + 1 si live_text == esperado y sandbox_text == esperado entonces result_table : insert ( '| ' , tick ) de lo contrario result_table : insert ( '| ' , cross ) num_failures = num_failures + 1 si live_text ~= esperado entonces highlight_live = verdadero fin si sandbox_text ~= esperado entonces highlight_sandbox = verdadero fin fin formato local = ( opciones y opciones . nowiki y mw . text . nowiki ) o return_varargs local difiere_en = self . difiere_en y ( ' \n | ' .. primera_diferencia ( esperado , texto_en_vivo ) o primera_diferencia ( esperado , texto_de_sandbox )) o '' tabla_resultado : insertar ( ' \n | ' , mw . texto . nowiki ( en vivo ), debería_resaltar y resaltar_en_vivo y ' \n | estilo="fondo: #fc0;"| ' o ' \n | ' , formato ( texto_en_vivo ), debería_resaltar y resaltar_sandbox y ' \n | estilo="fondo: #fc0;"| ' o ' \n | ' , formato ( texto_de_sandbox ), ' \n | ' , formato ( esperado ), difiere_en , " \n |- \n " ) fin de la función UnitTester : preprocess_equals_preprocess_many ( prefijo1 , sufijo1 , prefijo2 , sufijo2 , casos , opciones ) para _ , caso en ipairs ( casos ) hacer self : preprocess_equals_preprocess ( prefijo1 .. caso [ 1 ] .. sufijo1 , prefijo2 .. ( caso [ 2 ] y caso [ 2 ] o caso [ 1 ]) .. sufijo2 , opciones ) fin fin función UnitTester : preprocess_equals_sandbox_many ( módulo , nombre_función , casos , opciones ) para _ , caso en ipairs ( casos ) hacer local live = módulo .. "|" .. nombre_función .. "|" .. caso [ 1 ] .. "}}" sandbox local = módulo .. "/sandbox|" .. nombre_función .. "|" .. caso [ 1 ] .. "}}" self : preprocess_equals_compare ( live , sandbox , caso [ 2 ], opciones ) fin fin función UnitTester : equals ( nombre , actual , esperado , opciones ) num_runs = num_runs + 1 si actual == esperado entonces result_table : insert ( '| ' , tick ) de lo contrario result_table : insert ( '| ' , cross ) num_failures = num_failures + 1 fin formato local = ( opciones y opciones . nowiki y mw . text . nowiki ) o return_varargs local difiere_en = self . difiere_en y ( ' \n | ' .. primera_diferencia ( esperado , real )) o '' local display = opciones y opciones . mostrar o devolver_varargs result_table : insertar ( ' \n | ' , nombre , ' \n | ' , formato ( tostring ( mostrar ( esperado ))), ' \n | ' , formato ( tostring ( mostrar ( real ))), difiere_en , " \n |- \n " ) fin de la función local comparación_profunda ( t1 , t2 , ignore_mt ) ty1 local = tipo ( t1 ) ty2 local = tipo ( t2 ) si ty1 ~= ty2 entonces devuelve falso fin si ty1 ~= 'tabla' y ty2 ~= 'tabla' entonces devuelve t1 == t2 fin mt local = obtenermetatable ( t1 ) si no ignore_mt y mt y mt . __eq entonces devuelve t1 == t2 fin para k1 , v1 en pares ( t1 ) hacer v2 local = t2 [ k1 ] si v2 == nulo o no deep_compare ( v1 , v2 ) entonces devuelve falso fin fin para k2 , v2 en pares ( t2 ) hacer local v1 = t1 [ k2 ] si v1 == nil o no deep_compare ( v1 , v2 ) entonces devuelve falso fin fin devuelve verdadero fin función local val_to_str ( obj ) función local table_key_to_str ( k ) si tipo ( k ) == 'string' y mw . ustring . match ( k , '^[_%a][_%a%d]*$' ) entonces devuelve k de lo contrario devuelve '[' .. val_to_str ( k ) .. ']' fin fin si tipo ( obj ) == "string" entonces obj = mw . ustring . gsub ( obj , " \n " , " \\ n" ) si mw . ustring . match ( mw . ustring . gsub ( obj , '[^ \' "]' , '' ), '^"+$' ) entonces devuelve "'" .. obj .. "'" fin devuelve '"' .. mw . ustring . gsub ( obj , '"' , ' \\ "' ) .. '"' elseif tipo ( obj ) == "tabla" entonces resultado local , comprobado = {}, {} para k ,v en ipairs ( obj ) hacer tabla.insert ( resultado , val_a_str ( v )) comprobado [ k ] = verdadero fin para k , v en pares ( obj ) hacer si no está comprobado [ k ] entonces tabla.insert ( resultado , table_key_a_str ( k ) ... '=' ... val_a_str ( v )) fin fin devolver '{' ... tabla.concat ( resultado , ',' ) ... '}' de lo contrario devolver tostring ( obj ) fin fin función UnitTester : equals_deep ( nombre , actual , esperado , opciones ) num_runs = num_runs + 1 si deep_compare ( actual , esperado ) entonces tabla_resultado : insertar ( '|' , tick ) de lo contrario tabla_resultado : insertar ( ' | ' , cross ) num_failures = num_failures + 1 fin formato local = ( opciones y opciones.nowiki y mw . texto . nowiki ) o return_varargs local actual_str = val_to_str ( actual ) local esperado_str = val_to_str ( esperado ) local difiere_en = self . difiere_en y ( ' \n | ' .. primera_diferencia ( esperado_str , actual_str )) o '' tabla_resultados : insertar ( ' \n | ' , nombre , ' \n | ' , formato ( esperado_str ), ' \n | ' , formato ( actual_str ), difiere_en , " \n |- \n " ) fin de la función UnitTester : iterar ( ejemplos , func ) requiere 'libraryUtil' . checkType ( 'iterar' , 1 , ejemplos , 'tabla' ) si tipo ( función ) == 'cadena' entonces func = self [ función ] si no tipo ( función ) ~= 'función' entonces error (( "argumento incorrecto #2 para 'iterar' (función o cadena esperada, se obtuvo %s)" ) : formato ( tipo ( función )), 2 ) fin para i , ejemplo en ipairs ( ejemplos ) hacer si tipo ( ejemplo ) == 'tabla' entonces func ( self , desempaquetar ( ejemplo )) si no tipo ( ejemplo ) == 'cadena' entonces self : encabezado ( ejemplo ) si no error (( 'ejemplo incorrecto #%d (tabla esperada, se obtuvo %s)' ) : formato ( i , tipo ( ejemplo )), 2 ) fin fin fin función UnitTester : encabezado ( texto ) tabla_resultado : insertar_formato ( '!colspan="%u" estilo="text-align: left" | %s \n |- \n ' , self . columnas ,texto ) fin de la función UnitTester : ejecutar ( frame_arg ) frame = frame_arg self . frame = frame self . difiere_en = frame . args [ 'difiere_en' ] tick = frame : preprocess ( '{{Tick}}' ) cross = frame : preprocess ( '{{Cross}}' ) encabezado_tabla_local = encabezado_tabla_resultado si frame . args [ 'sandbox_en_vivo' ] entonces encabezado_tabla = encabezado_tabla_resultado_sandbox_en_vivo fin si frame . args . resaltar entonces debería_resaltar = verdadero fin self . columnas = 4 si self . difiere_en entonces encabezado_tabla = encabezado_tabla .. ' !! Difiere en' self . columnas = self . columnas + 1 fin -- Ordena los resultados en orden alfabético. local self_sorted = {} para clave , _ en pares ( self ) hacer si clave : buscar ( '^prueba' ) entonces tabla.insert ( self_sorted , clave ) fin fin tabla.sort ( self_sorted ) - Agregar resultados a la tabla de resultados. para _ , valor en ipairs ( self_sorted ) hacer tabla_resultados : insertar_formato ( encabezado_tabla .. " \n |- \n " , valor ) self [ valor ]( self ) tabla_resultados : insertar ( "|} \n " ) fin devolver ( num_runs == 0 y "<b>No se ejecutaron pruebas.</b>" o num_failures == 0 y "<b style= \" color:#008000 \" >Todas las " .. num_runs .. " pruebas pasaron.</b>" o "<b style= \" color:#800000 \" >" .. num_failures .. " de las " .. num_runs .. " pruebas fallaron.</b>[[Categoría:Casos de prueba de Lua fallidos usando Módulo:UnitTests]]" ) .. " \n\n " .. frame : preprocess ( result_table : concat ()) fin función UnitTester : new () local o = {} setmetatable ( o , self ) self . __index = self return o fin local p = UnitTester : new () función p . run_tests ( frame ) retorna p : ejecutar ( frame ) fin retorna p