Saltar al contenido principal
Cuando un paquete llama a comandos externos como ffmpeg o git, las diferencias de entorno de la aplicación que lo usa y los fallos se convierten directamente en el comportamiento del paquete. En lugar de llamar directamente a shell_exec() o exec(), ejecuta los comandos con la facade Process y sustitúyelos con Process::fake() en las pruebas.
Esta página se centra en Laravel 13 y revisa la implementación de Framework v13.42.0. Da por conocidos los procesos y las pruebas de paquetes. La coincidencia de comandos en array que se trata aquí se basa en cómo Symfony Process, que Process usa internamente, convierte los argumentos.

Por qué evitar la ejecución directa

Las llamadas directas a funciones no se pueden sustituir en las pruebas, y cada llamador gestiona los timeouts y los códigos de salida de forma distinta. Si pasas por la facade Process, unificas el registro de ejecuciones, los fakes, los timeouts y las excepciones en caso de fallo.

Pasa los comandos como array

Un comando en forma de string pasa por la interpretación de sh, así que si incluye datos del usuario aparecen problemas con las comillas y riesgo de inyección. Dentro del paquete, pasa los argumentos como array.
El timeout por defecto de PendingProcess es de 60 segundos y el timeout de inactividad es null. Para conversiones largas indica timeout() de forma explícita y, en procesos cuya salida puede detenerse, combínalo con idleTimeout().

Excepciones y mensajes en caso de fallo

ProcessResult::throw() lanza ProcessFailedException cuando el código de salida no indica éxito. El mensaje incluye el comando ejecutado, el código de salida y las salidas estándar y de error.
Si pones secretos en los argumentos del comando, quedarán incluidos en el mensaje de ProcessFailedException y pueden aparecer en logs o en pantalla. No pases tokens como argumentos. Pásalos con env() o escríbelos en el archivo de configuración del comando.
Los timeouts se representan con ProcessTimedOutException y los timeouts de inactividad con ProcessIdleTimedOutException. Documenta para los usuarios del paquete qué excepciones lanzas y qué pueden esperar al capturarlas.

Usa fakes en las pruebas

En las pruebas, sustituye los comandos externos con Process::fake(). Process::result() permite indicar la salida estándar, la salida de error y el código de salida.
Si pasas una closure a assertRan(), puedes comprobar command, timeout, environment y otras propiedades de PendingProcess. Los comandos en array se comparan con $process->command por coincidencia exacta, así que las pruebas detectan cambios en el orden o en los valores de los argumentos.

Claves de fake para comandos en array

Internamente, Process compara las claves de fake() con el resultado de getCommandline() usando Str::is(). Los comandos en array se convierten en un string con comillas para la shell, así que un patrón de string como 'ffmpeg*' no coincide. En las pruebas de comandos en array, usa una de estas opciones.

Evita comandos externos inesperados

Para detectar comandos externos que no deberían ejecutarse en las pruebas, usa preventStrayProcesses(). Los comandos que no coinciden con ningún fake lanzan RuntimeException y no llegan a iniciarse.

Si usas una Factory inyectada

Si el constructor del paquete recibe Illuminate\Process\Factory, comprueba que el estado de Process::fake() llega hasta la instancia inyectada. La facade guarda en caché la instancia resuelta y swap() reemplaza la instancia en el contenedor. En cambio, no puedes confiar en que el framework registre explícitamente Factory como compartida en el contenedor, así que compruébalo en una prueba. Si el fake no llega a la instancia inyectada, sustituye la Factory de forma explícita en la prueba o diseña el paquete para que pase por la facade Process. En ambos casos, comprobar con assertRan() que la llamada quedó registrada te permite detectar una sustitución olvidada.

Comprobaciones para el mantenimiento a largo plazo

Fuentes primarias consultadas

Última modificación el 13 de noviembre de 2026