Laboratorio — Entorno de trabajo
Todo el trabajo práctico del curso (ejemplos de clase, laboratorios y el proyecto Bodega) se compila y se prueba dentro de un contenedor Docker idéntico para todos, con el JDK 25 y JUnit ya instalados. Así evitamos el “en mi computadora sí funciona”: si las pruebas pasan en el contenedor, pasan en la revisión.
1. Requisitos
| Sistema | Qué instalar |
|---|---|
| Linux | Docker Engine |
| Windows 10/11 | WSL2 + Docker Desktop con integración WSL. Trabajen dentro del sistema de archivos de WSL (~/), no en C:\. |
| macOS (Intel o Apple Silicon) | Docker Desktop |
La imagen es nativa: en una laptop con procesador ARM (Apple Silicon, por ejemplo) corre como ARM, y en una con procesador Intel o AMD corre como x86-64. No hay emulación, así que compilar y correr las pruebas es rápido.
Si no pueden instalar Docker, vean la sección 6.
2. Levantar el contenedor
Desde la carpeta del repositorio del curso (o la de su proyecto):
./env/run.sh # la primera vez construye la imagen (unos minutos)
run.sh monta el directorio actual en /work dentro del contenedor. Los
archivos se editan con el editor de siempre en su computadora y se compilan y
ejecutan en el contenedor. También acepta un comando:
./env/run.sh make -C code/week-03 test
./env/run.sh --rebuild # reconstruye la imagen (si cambió el Dockerfile)
Si su proyecto está en otra carpeta, llamen a run.sh con su ruta desde esa
carpeta: /ruta/al/curso/env/run.sh.
La imagen (env/Dockerfile, basada en Eclipse Temurin 25) incluye:
- el JDK 25:
javac,java,jshell,javadoc,jar - JUnit 6 en un solo jar, en la ruta de la variable
$JUNIT_JAR make,gity los editores de terminalvimynanogcc, para compilar los ejemplos en C que comparamos con Java (semana 1)
3. Java desde la terminal
jshell: probar una idea en segundos
jshell evalúa expresiones y declaraciones de Java una por una, sin crear un
archivo. Sirve para explorar la API y para probar un método antes de
escribirlo en una clase.
$ jshell
jshell> var nombres = new java.util.ArrayList<String>();
jshell> nombres.add("arroz");
jshell> nombres.size()
$3 ==> 1
jshell> /exit
/help muestra los comandos; /vars y /methods listan lo que se definió.
Un archivo: java Archivo.java
Un programa de un solo archivo se ejecuta sin compilarlo antes: java lo
compila en memoria y lo corre. Desde Java 25 el archivo puede ser compacto,
sin declarar la clase (JEP 512):
// Hola.java
void main() {
IO.println("Hola, " + 2 * 21);
}
java Hola.java
Así trabajamos en las semanas 1 y 2. Desde la semana 3 el código va en clases normales, en varios archivos.
Varios archivos: javac y java
javac -Xlint:all -d build *.java # compila; los .class quedan en build/
java -cp build Main # ejecuta la clase Main
-Xlint:all activa todos los warnings: el código del curso compila sin
ninguno. -cp (class path) le dice a java dónde buscar las clases
compiladas. Con paquetes, el nombre de la clase va completo:
java -cp build bodega.Main.
4. make y las pruebas con JUnit
Cada carpeta code/week-NN/ (y cada entrega del proyecto) trae un Makefile:
| Comando | Qué hace |
|---|---|
make |
Compila todo a build/ |
make test |
Compila, corre los programas de demostración y las pruebas JUnit (*Test.java) |
make clean |
Borra build/ |
Por dentro, make test hace algo como esto:
javac -Xlint:all -d build -cp "$JUNIT_JAR" *.java
java -jar "$JUNIT_JAR" execute --class-path build --scan-class-path
Una prueba es un método con @Test en una clase cuyo nombre termina en Test:
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.Test;
class CounterTest {
@Test
void incrementAddsOne() {
Counter c = new Counter(5);
c.increment();
assertEquals(6, c.value());
}
}
Al final, JUnit imprime un resumen: tests successful y tests failed. Si
una prueba falla, muestra el valor esperado, el obtenido y el stack trace.
Para correr solo una clase de prueba:
java -jar "$JUNIT_JAR" execute --class-path build --select-class CounterTest.
5. Editar el código
Cualquier editor sirve, porque se compila en el contenedor. Recomendamos uno que entienda Java (autocompletado, errores mientras escriben, refactoring):
- VS Code con el Extension Pack for Java.
- IntelliJ IDEA Community Edition, gratuito: https://www.jetbrains.com/idea/download/.
Para que el editor no marque errores en las pruebas, necesita conocer el jar de
JUnit (ver la sección 6). Aunque el editor compile por su cuenta, la referencia
es siempre make test en el contenedor.
6. Alternativa: JDK local y un editor
Si no pueden usar Docker, instalen un JDK 25 en su computadora; por ejemplo, Eclipse Temurin. Comprueben la versión:
java -version # debe decir 25
Descarguen el jar de JUnit (el mismo que trae la imagen) y apunten JUNIT_JAR a él:
mkdir -p ~/lib
curl -fL -o ~/lib/junit.jar \
https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console-standalone/6.1.3/junit-platform-console-standalone-6.1.3.jar
export JUNIT_JAR=~/lib/junit.jar # agréguenlo a ~/.bashrc o ~/.zshrc
Con eso, make test funciona igual que en el contenedor (en Windows, dentro de
WSL). En VS Code o IntelliJ agreguen junit.jar como biblioteca del proyecto.
Antes de entregar, corran las pruebas al menos una vez en el contenedor.
7. Solución de problemas
| Síntoma | Causa probable |
|---|---|
Cannot connect to the Docker daemon |
Docker Desktop no está abierto. |
error: class X is public, should be declared in a file named X.java |
El nombre del archivo no coincide con el de la clase pública. |
Error: Could not find or load main class Main |
Falta -cp build, o la clase está en un paquete y hay que escribir el nombre completo. |
package org.junit.jupiter.api does not exist |
Falta -cp "$JUNIT_JAR" al compilar, o JUNIT_JAR no está definida (JDK local). |
JUnit dice 0 tests found |
La clase de prueba no termina en Test, falta @Test, o no se compiló a build/. |
Unknown options: '--class-path' |
Falta el subcomando execute después de -jar "$JUNIT_JAR". |
unsupported class file major version |
Se compiló con un JDK distinto del que ejecuta; usen JDK 25 para ambos. |
Archivos cuyo owner es root en su computadora (Linux) |
Agregar --user "$(id -u):$(id -g)" al docker run de run.sh. |
| Todo muy lento en Windows | El código está en C:\; muévanlo a ~/ dentro de WSL. |