[Off] Code coverage para pawn?
#1

Sу estava pensando mesmo aqui, o quгo ъtil seria uma avaliaзгo do seu script pawn com "code coverage", para criar esta ferramenta eu me basearia nos mйtodos, formas de uso, configuraзхes etc... de Coverage.py

Os passos para atingir este resultado seria o mesmo, porйm em pawn atualmente nгo existem mйtodos para fazer um trace do cуdigo pawn linha por linha, entгo isto й o que precisa ser feito, porйm neste passo eu me perdi totalmente nгo consegui imaginar um mйtodo para qual, alguйm tem uma ideia uma luz?

@Edit tive uma ideia que parece funcional, porйm nгo viбvel com um servidor em produзгo
Programa para compilar o cуdigo
  • compila primeiramente com -l ativo
  • apуs percorre todas linhas inserindo em cada linha valida para o run time o seguinte trecho:
    PHP код:
    coverageExec(__line); 
  • As linhas invбlidas seriam definidas como executada pelo prуpio programa
  • O cуdigo de exemplo basicamente seria este
    PHP код:
    main()
    {
    coverageExec(__line);
        if(
    truecoverageExec(__line);
        { 
    coverageExec(__line);
            
    coverageExec(__line); print("example-1");
        } 
    coverageExec(__line);
        else 
    coverageExec(__line);
        { 
    coverageExec(__line);
            
    coverageExec(__line); print("example-2");
        } 
    coverageExec(__line);
        
    coverageExec(__line);} 
Para quem nгo sabe do que se trata, devmedia explica

A ferramenta basicamente faria isto:
  • Temos o seguinte cуdigo
    PHP код:
    main()
    {
        if(
    true)
        {
            print(
    "example-1");
        }
        else
        {
            print(
    "example-2");
        }

  • Logo ele teria 63.63 % de cobertura, jб que a condicional if nunca permitiria que o else seja executado, tendo uma saida como:
    > = executado
    ! = perdido
    PHP код:
    main()
    > {
    >     if(
    true)
    >     {
    >         print(
    "example-1");
    >     }
    !     else
    !     {
    !         print(
    "example-2");
    !     }
    > } 
Reply
#2

Muitos ja tem tentado e alguns conseguem trazer o Python para o pawn.

Gostei do que voce apresentou agora o povo mais novo que nao entende tanto da matйria muito menos de Python perguntam, para que isto serve?


Anyway й bom ver que voce ainda ca continua eu ando meio ausente, obrigado por compartilhar isso.
Reply
#3

Muito interessante. Realmente o pawn esconde muitas coisas.
Reply
#4

Seria muito ъtil criar um teste unitбrio em Pawn, tambйm seria de grande utilidade para encontrar bugs ou aplicar correзхes de desempenho e etc.

Jб pensastes em criar uma aplicaзгo externa pra gerar um code coverage para Pawn?
Reply
#5

TDD para Pawn, se tratando de desenvolvimento SA-MP nгo valeria a pena. Como o desenvolvimento SA-MP й todo baseado em callbacks e a grande maioria das funcionalidades sгo ligadas a aзхes na tela do usuбrio o TDD ficaria quase que 100% sу de mocks, o que nгo testaria nada.

E sobre o code coverage tambйm acho totalmente desnecessбrio. No caso do exemplo do if, o compilador iria lanзar uma exception informando que existe uma parte do cуdigo que nunca serб executada (Pawn error (225) Unreachable Code error ) nгo sendo necessбrio um coverage.

Й bacana ver que a galera estб entrando mais nessa parte teуrica de programaзгo porйm muita coisa nгo й necessбria ou nгo se aplica quando se trбs para o Pawn (SA-MP)
Reply
#6

@PT Jб havia um pequeno trecho do tуpico dando um exemplo, porйm agora eu referкnciei uma matйria do DevMedia

@Adiiti isto й basicamente uma gambiarra, jб que o pawn nгo oferece suporte a um trace completo como este.

@Bruno13 para rodar o teste, haverб trкs items sendo eles:
  • Obrigatуrio
    • prй-compilador
      Serб escrito em go, pois usarб Template based pre-compile, para detectar coisas como: defined, endinput.
      O prй-compilador irб fazer o seguinte:
      • inserir em cada linha vбlida uma funзгo para passar ao plugin que estб linha foi executada, ou talvez apenas antes e apуs condicionais, para melhorar o desempenho
      • Inicializar o plugin(hook ongamemodeinit), com alguns dados como: numero max de linhas, linhas executadas na parte de compilaзгo(globais)
    • plugin
      Para melhorar o desempenho eu opto por um plugin para gerar o coverage, ele farб a funзгo de gerar um arquivo em um formato para ser lido pelo coverage.py, e uma funзaх para obter o report, durante o run time(calculo)
  • Opcional
    • coverage.py, lк o arquivo gerado pelo plugin e...
@Kamper um projeto recente meu estб todo baseado em TDD, fazendo simulaзхes, se bem feito pode vir a funcionar ^.^
Ele trata as simulaзхes indiretamente, algo como:
PHP код:
AddFakePlayer(playeridname[], ...) 
Apуs isto todas funзхes nativas como: getplayername, isplayerconnected, getplayerip, getplayerpos, retornam dados desse player fake.

Callbacks para ele eu aciono-as com AddPlayerEvent

Outros testes que nгo necessitam disto, eu uso um fork meu do y_test do ******

Talvez em algumas semanas, eu publique isto, para ajudar a board..

Sobre o erro 225 ele ocorre apenas csao isto aconteзa:
PHP код:
func()
{
    return 
1;
    new 
a;
    return 
a;

Reply
#7

Quote:
Originally Posted by Dayvison_
Посмотреть сообщение
@PT Jб havia um pequeno trecho do tуpico dando um exemplo, porйm agora eu referкnciei uma matйria do DevMedia

@Adiiti isto й basicamente uma gambiarra, jб que o pawn nгo oferece suporte a um trace completo como este.

@Bruno13 para rodar o teste, haverб trкs items sendo eles:
  • Obrigatуrio
    • prй-compilador
      Serб escrito em go, pois usarб Template based pre-compile, para detectar coisas como: defined, endinput.
      O prй-compilador irб fazer o seguinte:
      • inserir em cada linha vбlida uma funзгo para passar ao plugin que estб linha foi executada, ou talvez apenas antes e apуs condicionais, para melhorar o desempenho
      • Inicializar o plugin(hook ongamemodeinit), com alguns dados como: numero max de linhas, linhas executadas na parte de compilaзгo(globais)
    • plugin
      Para melhorar o desempenho eu opto por um plugin para gerar o coverage, ele farб a funзгo de gerar um arquivo em um formato para ser lido pelo coverage.py, e uma funзaх para obter o report, durante o run time(calculo)
  • Opcional
    • coverage.py, lк o arquivo gerado pelo plugin e...
@Kamper um projeto recente meu estб todo baseado em TDD, fazendo simulaзхes, se bem feito pode vir a funcionar ^.^
Ele trata as simulaзхes indiretamente, algo como:
PHP код:
AddFakePlayer(playeridname[], ...) 
Apуs isto todas funзхes nativas como: getplayername, isplayerconnected, getplayerip, getplayerpos, retornam dados desse player fake.

Callbacks para ele eu aciono-as com AddPlayerEvent

Outros testes que nгo necessitam disto, eu uso um fork meu do y_test do ******

Talvez em algumas semanas, eu publique isto, para ajudar a board..

Sobre o erro 225 ele ocorre apenas csao isto aconteзa:
PHP код:
func()
{
    return 
1;
    new 
a;
    return 
a;

Tem um trecho de cуdigo para poder me mostrar?
Reply
#8

Quote:
Originally Posted by Kamper
Посмотреть сообщение
Tem um trecho de cуdigo para poder me mostrar?
Aqui neste trecho vocк pode ver a parte baseada em simulaзхes(OnPlayerEvent, clickTextDraw, inputDialog), e tambйm os testes comuns ASSERT

Atualmente tenho feito apenas estes eventos, e algumas hooks bбsicas, eu pretendo ir incrementando conforme for necessбrio.

PHP код:
#include <tests>
#include <hooks>
/*
    Passos
1. Adcionar o player(nгo registrado)
2. Testar outros botхes de textdraws
3. Registrar o player
4. Checar no banco de dados se os dados foram inseridos
5. Setar valores nas variaveis dele
6. Remover o player
7. Checar no DB se os dados sгo iguais aos setados
8. Conectar o player(registrado), no id do player acima
9. Checar se variaveis foram limpas
10. Logar o player
11. Mudar valor das variaveis
12. Desconectar o player
13. Checar no DB se os valores foram atualizados
*/
static uvar(string:      test_String[MAX_PLAYERS][15])        = "string",     "\0";
static 
uvar(Float:       test_Float[MAX_PLAYERS])             = "float",       0.0;
static 
uvar(Float:       test_ArrayFloat[MAX_PLAYERS][15])    = "array-float"0.0;
static 
uvar(bool:        test_Bool[MAX_PLAYERS])              = "bool",        false;
static 
uvar(bool:        test_ArrayBool[MAX_PLAYERS][15])     = "array-bool",  false;
static 
uvar(             test_Int[MAX_PLAYERS])               = "int",          0;
static 
uvar(             test_ArrayInt[MAX_PLAYERS][15])      = "array-int",   0;
static 
uvar(BitArray:    test_BitArray<MAX_PLAYERS>)          = "bitarray",    false;
Test:Init()
{
        const 
playerid 0;
    
// 1. Adcionamos um player(nгo registrado)
    
AddFakePlayer(playerid"Unknown_User""127.0.0.1", {130230});
}
hook OnPlayerEvent(playeridplayerEvents:eventid)
{
    static 
step;
    if(
eventid == SELECT_TEXTDRAW)
    {
        
// 2. Testar outro botгo
        
if(!step)
        {
            ++
step;
            
clickTextDraw(playeridloginSignIn[2]);
        }
        else
        {
            
// 3. Registrar o player
            
step 0;
            
clickTextDraw(playeridloginSignUp[2]);
        }
        return;
    }
    
// Certificar de que quando clica no botгo logar, sem estar conectado nada aconteзa
    
ASSERT(!step);
    if(
eventid == DIALOG_INPUT)
    {
        
// 3. Registrar o player
        
inputDialog(playerid"12345");
    }
}
hook OnPlayerLogin(playeridloginType:type)
{
    
// 3. Registrar o player
    
if(type == login_byRegister)
    {
        
// Seleciona os dados da tabela
        
format(gs_QueryBuffersizeof(gs_QueryBuffer), "SELECT * from `"#USERS_TABLE"` where `id`='%d';", getPlayerIDG(playerid));
        
new Cache:cache mysql_query(cHandlegs_QueryBuffer);
        
// Obtem o numero de linhas existentes
        
new rows;
        
cache_get_row_count(rows);
        
        
// Certificar que a linha existe
        
ASSERT(rows == 1);
        
// 4. Checa no banco de dados se os dados foram inseridos
        
new 
            
value_Arrays[15*15], // Salvo em strings, depois convertidos para indices
            
value_String[15],
            
Float:value_Float,
            
Float:value_ArrayFloat[15],
            
value_Bool,
            
bool:value_ArrayBool[15],
            
value_Int,
            
value_ArrayInt[15],
            
value_BitArray
        
;
        
cache_get_value_name(0,       "string",      value_String);
        
ASSERT(strcmp(value_Stringtest_String[playerid]));
        
cache_get_value_name_float(0"float",       value_Float);
        
ASSERT(value_Float == test_Float[playerid]);
        
cache_get_value_name(0,       "array-float"value_Arrays);
        
sscanf(value_Arrays"p<,>a<f>[15]"value_ArrayFloat)
        
ASSERT(arraycmp(value_ArrayFloattest_ArrayFloat[plyerid]));
        
cache_get_value_name_int(0,   "bool",        value_Bool);
        
ASSERT(value_Bool == test_Bool[playerid]);
        
cache_get_value_name(0,       "array-bool",  value_Arrays);
        
sscanf(value_Arrays"p<,>a<d>[15]"_:value_ArrayBool)
        
ASSERT(arraycmp(value_ArrayBooltest_ArrayBool[plyerid]));
        
cache_get_value_name_int(0,   "int",         value_Int);
        
ASSERT(value_Int == test_Int[playerid]);
        
cache_get_value_name(0,       "array-int",   value_Arrays);
        
sscanf(value_Arrays"p<,>a<d>[15]"value_ArrayInt)
        
ASSERT(arraycmp(value_ArrayInttest_ArrayInt[plyerid]));
        
cache_get_value_name_int(0,   "bitarray",    value_BitArray);
        
ASSERT(value_BitArray == _:Bit_Get(test_BitArrayplayerid));
    }

Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)