¿Cómo evalúan los sitios web como codecademy.com y teamtreehouse.com el código ingresado por el usuario?

Trabajo en Treehouse y he trabajado en nuestra plataforma de ejecución de código y he creado las herramientas que nuestros maestros usan para crear desafíos de código.

De hecho, ejecutamos su código. Protegemos cada solicitud que ingresamos, establecemos el contexto en el que le pedimos que escriba el código, ejecute su código y luego ejecute las pruebas unitarias que nuestro personal docente ha escrito para analizar su código. Hacemos esto en todos y cada uno de los idiomas que admitimos. La capa de orquestación está escrita en Ruby, y usamos Docker para sandboxing.

Por ejemplo, cuando trabajas en un Desafío de código de Python, haces clic en Enviar, tu código se envía a nuestro servidor, una aplicación Ruby establece un contexto de Python, ejecuta tu código de Python en él y luego ejecuta las pruebas unitarias del profesor en el contexto resultante para Busque los efectos secundarios adecuados. Python devuelve los resultados a nuestra aplicación Ruby, y esa aplicación devuelve los resultados al alumno.

Creamos estos desafíos en una aplicación web separada que serializa todos los detalles del Code Challenge y posteriormente los publica. Los maestros escriben el guión de prueba y también escriben pruebas de integración con posibles respuestas enviadas, si esperan que la respuesta pase o no el desafío, y con qué mensaje. Los maestros tratan de cubrir las formas más comunes en que un estudiante fallará el desafío para que reciban mensajes de error útiles. Ejecutamos todas estas pruebas contra todos los desafíos de código en vivo cuando es necesario para buscar regresiones, como cuando actualizamos las versiones del sistema operativo o movemos cuadros.

Como también respondió Justen Robertson, siempre que sea posible, probamos los resultados de su código, no el código en sí mismo. Esto evita la trampa de buscar una “forma correcta” para resolver el problema cuando todos sabemos que el software no es una búsqueda lineal. Solo analizamos el código en sí cuando trabajamos con un lenguaje compilado que puede fallar en la compilación, o cuando verificamos el uso adecuado de una función de lenguaje.

Hacer esto bien contra muchos idiomas y entornos diferentes es difícil . Sin embargo, creemos que los resultados valen la pena.

No sé acerca de estos dos sitios específicos, pero el caso general es utilizar pruebas unitarias, que es el término técnico para su primera suposición. Trataré de explicar por qué usa esta opción y no la otra que adivinó.

Por lo tanto, hay funcionalmente un número infinito de formas de realizar una tarea en particular, especialmente cuando se llega a opciones irrelevantes, como nombres variables y espacios en blanco. Si intentara enumerar todos los fragmentos de código posibles que satisfarían una especificación dada, nunca terminaría el trabajo. La opción mucho mejor es probar que un fragmento de código produce la salida esperada dada una entrada.

Suponga que su pregunta de prueba es:

Escriba una función “multiplyByFive” que, dado un entero como su único parámetro, devuelva la entrada multiplicada por cinco

Probar esto se ve más o menos así:

  deje que la entrada sea 5
 deje que la salida esperada sea 25
 llame a multiplyByFive con entrada, devolviendo salida
 afirmar que la salida es igual a la esperada

Estoy más familiarizado con javascript, así que lo usaré para un ejemplo más concreto. Hay muchas formas de hacer esto en JS:

  función multiplyByFive (x) {return x + x + x + x + x;}

o:

  var multiplyByFive = función (a) {
	 var b = a * 5;
	 volver b;
 }

o:

  let multiplyByFive = (input) => input * 5;

o:

  función multiplyByFive (n) {
	 para (var i = 0; i <5; ++ i) n + = n;
	 volver n;
 }

Dada la variabilidad sustancial en estos códigos técnicamente correctos, ¿cómo sabe que el código es correcto? No es posible poner todas estas variaciones, más los millones de otras variantes, en una gran pila de archivos javascript y probar si la respuesta del alumno es la misma que una de ellas.

En cambio, utiliza una prueba unitaria. Suponga que la prueba de la unidad incluye el código enviado por el estudiante. Así es como se vería una prueba básica:

  entrada var = 5;  // configurar la entrada
 salida var = multiplyByFive (input);  // llama a la función del alumno
 afirmar.equal (salida, 25);  // lanza una excepción si la entrada no es igual a 25

Una prueba de unidad del mundo real sería más exhaustiva (comprobar que la función realmente existe, que devuelve respuestas correctas para un rango de entradas, comprobar que no acepta entradas no válidas, etc.). Sin embargo, este es el concepto básico de la cosa.

Al hacerlo de esta manera, a su prueba no le importan los detalles de la implementación, solo que produce el resultado esperado. Si la prueba de la unidad falla, la respuesta se marcará como incorrecta.

¡Lo has pensado bien!
Comparan nuestra respuesta con un montón de posibles respuestas para verificar la corrección, aunque en algunos casos solo es posible una respuesta (¡ese es un caso diferente!)

Para cosas HTML, el iframe se usa para mostrarnos la salida de nuestro código. Y la actualización en tiempo real se realiza a través de llamadas AJAX . Para enseñar el código de aplicación de la consola se usa algo como esto: JQuery Console Demo

¡Espero que esto ayude!