Scenery é uma ferramenta de criação de cenários para testes de integração e validação de expectativas nas camadas da aplicação/domínio e infra estrutura que permite execuções ciclicas(repetições do conjunto de ações) para simulações de comportamento real de uso.
####Inspiração####
"A gente devia ter duas vidas, uma pra ensaiar e outra para viver." (Vittorio Gassman)
###Scenery###
Um cenário é uma configuração de ambiente para execução e teste de expectativas de um conjunto de Ações.
As caracteristicas de um cenário são:
- Conjunto inicial de dados.
- Conjunto de ações.
- Estratégia de execução.
####Criando um cenário####
$initialDataState = new Data();
$scenery = new Scenery($initialDataState);
###Action###
Action é um comportamento existente em um Domínio cujo efeito pode ser testado utilizando expectativas.
características de uma Action:
- uma Action tem um estado composto por
-
estado dos Dados
- New: Os dados no estado atual do cenário.
- Old: Os dados no estado anterior a execução da Action.
-
transienteData: Dados temporários no escopo da ação e suas expectativas:
- Cycle: O número identificador do ciclo de execução em que esta o cenário.
- udd: user defined data. Dados transientes definidos pela action necessários para sua execução e/ou teste de expectativas.
-
####Criando uma ação####
$action = function($state){
// comportamento do domínio ou aplicação.
}, function($state){
// expectativa do domínio.
}, function ($state){
// expectativa na infra estrutura.
}
);
// adicionando a action em um cenário.
$scenery->action([Nome da Action], $action);
Expectativa é uma verificação dos efeitos relacionados a execução de uma ação.
Caracteristicas de uma expectativa:
- São dois tipos de expectativa.
- layer de Domínio (expectedDomain): utiliza código de domínio para validar a Action.
- layer de infra estrutura (expectedInfraStructure): utiliza recursos de infra estrutura para validar a Action.
- cada tipo de expectativa tem seu conjunto de assertions.
O estado do dados é representado por uma estrutura de array representando o modelo dos dados utilizados.
Se um sistema utiliza uma tabela modelada como
create table Person
(
id serial primary key,
name varchar(100),
email varchar(100)
)
O estado dos dados após inserir uma person de nome 'Ivo' e email 'iannsp@gmail.com' é.
$dsn ='sqlite:/tmp/sceneryTest.sq3';
$pdo = new \PDO( $dsn);
$pdo->exec('
drop table person;
create table person(id integer primary key, name CHARACTER(100), email CHARACTER(100))');
$pdo->exec("insert into person (name, email) values ('Ivo','iannsp@gmail.com')");
// usei o hack pq clone esta dando segmentFault(precisa verificar o que estou fazendo de errado ou se é bug).
$pdo->newFromDsn = new \PDO( $dsn);
####Exemplo de Cenário####
Caracteristicas:
- tem somente uma ação chamada Criar Pessoa.
- sua estratégia de execução é por Número de Ciclos e sera executado 1 vez.
// require o bootstrap da aplicação.
require 'bootstrap.php';
// cria o cenário utilizando um conjunto de dados inicial.
$scenery = new Scenery($pdo);
// adiciona a Action Criar Pessoa
$scenery->action('Criar Pessoa', function($state){
// código da Action
$instanciaDeServicoDePessoa = new \Domain\Service\Person();
$state->addTransienteData('person', ['nome'=>'Ivo','email'=>'iannsp@gmail.com']);
$instanciaDeServicoDePessoa->create('Ivo', 'iannsp@gmail.com');
}, function($state){
// teste de Domain layer.
$person = $state->getTransienteData('person');
$instanciaDeServicoDePessoa = new \Domain\Service\Person();
$persons = $instanciaDeServicoDePessoa->find(['nome'=>'Ivo']);
$state->assertCount(1,$persons);
$state->assertEquals($persons[0]->get('nome'), $person['nome']);
}, function($state){
// teste de infra estrutura
$newPersons = $state->new->get(['person'=>[]]);
$oldPersons = $state->old->get(['person'=>[1]]);
$state->assertCount(0, $oldPersons);
$state->assertCount(1, $newPersons);
}
);
// executando o cenário com uma estratégia de execucação por número de ciclos.
$runnerStrategy = factory::get(Strategy::RUN_BY_CYCLE_NUMBER,$scenery);
$results = $runnerStrategy->run(1);
//executando o cenário durante meia hora com intervalo(by) de 1 segundo entre cada iteracao.
$executarDuranteMeiaHora = new \Datetime();
$executarDuranteMeiaHora->add(new \DateInterval("P0YT30M0S"));
$runnerStrategy = factory::get(Strategy::RUN_UNTILDATE,$scenery);
$results = $runnerStrategy->run(['until'=>$executarDuranteMeiaHora,'by'=>1]);