Code frameworks
Pruebas con escenarios
Crea un Elemento, ejecuta acciones y comprueba cada valor y cada escritura.
Qué contiene un escenario
Un escenario es un archivo JSON de scenarios/. Crea un Elemento a partir de entradas, ejecuta acciones en orden y comprueba los resultados. El manifiesto enumera cada archivo de escenario, y cada archivo contiene un escenario.
{
"id": "heal-after-damage",
"framework": "keeper",
"parameters": { "name": "Mira", "max_hp": 10 },
"expectedValues": { "name": "Mira", "max_hp": 10, "hp": 10 },
"actions": [
{
"action": "hurt",
"parameters": { "amount": 6 },
"expectedWrites": [{ "op": "ledger.add", "key": "hp", "value": -6 }]
},
{
"action": "heal",
"parameters": { "amount": 9 },
"expectedWrites": [{ "op": "ledger.set", "key": "hp", "value": 10 }]
},
{ "action": "heal", "parameters": { "amount": 3 }, "expectedWrites": [] }
]
}- Líneas 4-5 Crea el Elemento con estas entradas y comprueba sus valores iniciales.
- Línea 6 actions enumera los pasos que se ejecutan, en orden.
- Línea 10 Las escrituras exactas que debe hacer el paso.
- Línea 17 Sin escrituras: no cambió nada.
| Campo | Significado |
|---|---|
| id | El nombre del escenario. |
| framework | El id del Framework que se va a crear. |
| parameters | Las entradas con las que se crea. |
| expectedValues | Cada valor guardado justo después de la construcción. |
| expectedChildren | Los valores de cada ranura hija. |
| actions | Pasos que se ejecutan, 32 como máximo por escenario. Cada uno tiene una action, sus parameters y expectedWrites. |
| ledger | Comprobaciones de valores derivados. |
| lists | Llena una lista con entradas, por id de preajuste. |
| expectedLists | Las entradas que tiene cada lista al final, por id de preajuste. |
| poolRolls | Tiradas registradas para un pool que usa el método roll, por id de pool. Consulta Puntuaciones tiradas. |
| content | Entradas de contenido fijadas al Element construido (kind, entryId, name y parameters), que se combinan en la versión igual que las fijaciones de un personaje. |
Un paso puede usar más campos:
| Campo del paso | Significado |
|---|---|
| choose | Para una acción de lista: la entrada que elige el jugador para cada entrada ContentRef, por id de preajuste. |
| expectedRefusal | El rechazo con el que debe terminar el paso. Entonces el paso no espera escrituras. |
| expectedValuesAfter | Valores guardados y derivados después del paso. Los valores derivados se recalculan primero. |
Escrituras
expectedWrites enumera cada escritura que hace el paso, en orden. Usa ledger.set para un valor establecido y ledger.add para una cantidad sumada. Un paso que no cambia nada no enumera escrituras, así que también se prueba la guarda que omite una escritura.
Si las escrituras reales son distintas, la comprobación muestra ambas listas.
"expectedWrites": [{ "op": "ledger.set", "key": "hp", "value": 9 }]Expected ordered writes [{"op":"ledger.set","key":"hp","value":9}]; observed [{"op":"ledger.set","key":"hp","value":10}].Valores derivados e hijos
La lista ledger comprueba una función de ledger. Indica el id de la función, el valor de partida y el valor que debe devolver. expectedChildren comprueba los Elementos hijos.
"expectedChildren": { "lamp": { "name": "Lantern", "oil": 5 } },- Línea 17 Comprueba los Elementos de las ranuras hijas.
"ledger": [{ "function": "guard", "currentValue": 0, "expected": 3 }]- Línea 18 Llama a la función de protección con el valor actual 0 y espera 3.
Qué hay que cubrir
- Cada constructor, acción y función de ledger necesita un escenario.
- Cada acción necesita al menos un paso. Añade un paso por cada rama que quieras probar, como uno que escribe y otro que no escribe nada.
- Una acción que añade a una lista necesita un paso aceptado y un paso con expectedRefusal, diga lo que diga su oferta. El paso rechazado demuestra que la oferta puede decir que no. Una acción que solo quita de una lista necesita un paso aceptado.
- Los valores esperados deben coincidir con lo que el constructor devuelve de verdad, con las funciones del ledger ya aplicadas.
Los pasos se nombran según su escenario. Un mensaje como heal-after-damage-2 significa el tercer paso de heal-after-damage, porque el número cuenta desde 0. Otros mensajes cuentan los pasos desde 1.
Un paso que dice esperar un rechazo de una acción que no se rechazó falla, y también falla lo contrario:
the step expects it to be refused with NOT_OFFEREDAdd expectedRefusalUna acción sin ningún paso falla con:
SELF_SCALAR_ACTION_SCENARIO_COVERAGE_MISSING: action keeper.hurt (Take damage) has no executable scenario steps.Una acción de lista a la que le falta un paso aceptado o rechazado falla con:
add a step with expectedRefusal, so its refused branch is proven.add a step whose list.add is accepted, so its accepted branch is proven.Los valores esperados que difieren del constructor fallan con:
Constructor output does not match its scenario.Rechazos
Una acción de lista puede ser rechazada. Un paso que lo espera nombra el código en expectedRefusal y no enumera escrituras.
| Código | Cuándo |
|---|---|
| NOT_OFFERED | La entrada elegida no está entre las que permite la oferta. |
| ALREADY_IN_LIST | La lista ya tiene la entrada. |
| LIST_FULL | La lista está en su tamaño máximo. |
| NOT_IN_LIST | list.remove nombra una entrada que la lista no tiene. |
| LIST_CAP | Se superaría un límite que declara la lista. |
| SAME_NAME | La lista ya tiene una entrada con ese nombre. |
Este proyecto demuestra varios de ellos. También tiene un paso en el que una guarda detiene la acción, así que el paso no espera escrituras ni rechazo.
{
"id": "pack-trinkets",
"framework": "keeper",
"parameters": { "name": "Mira", "max_hp": 10 },
"expectedValues": { "name": "Mira", "max_hp": 10, "hp": 10 },
"actions": [
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedWrites": [{ "op": "list.add", "key": "pack", "value": "rope" }]
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedRefusal": "ALREADY_IN_LIST",
"expectedWrites": []
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "anvil" },
"expectedRefusal": "NOT_OFFERED",
"expectedWrites": []
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "candle" },
"expectedWrites": [
{ "op": "list.add", "key": "pack", "value": "candle" }
]
},
{
"action": "pack_trinket",
"parameters": {},
"choose": { "trinket": "bell" },
"expectedWrites": []
},
{
"action": "unpack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedWrites": [
{ "op": "list.remove", "key": "pack", "value": "rope" }
]
},
{
"action": "unpack_trinket",
"parameters": {},
"choose": { "trinket": "rope" },
"expectedRefusal": "NOT_IN_LIST",
"expectedWrites": []
}
],
"expectedLists": { "pack": ["candle"] }
}- Líneas 7-12 Aceptado: list.add escribe la cuerda.
- Líneas 13-19 Rechazado: la lista ya tiene la cuerda.
- Líneas 20-26 Rechazado: la oferta no permite el yunque.
- Líneas 35-40 La mochila ya tiene dos entradas, así que la guarda no escribe nada y no se espera ningún rechazo.
- Líneas 41-48 Quitado: la cuerda sale de la lista.
- Líneas 49-55 Rechazado: la cuerda ya no está en la lista.
- Línea 57 La mochila termina solo con la vela.
Ejecutarlos
Comprobar y previsualizar en The Forge compila el proyecto y ejecuta cada escenario. No se publica nada y no cambia ningún personaje en vivo.

