A importancia de fazer testes
Tags: php, testing, tip, beginners
Published: 2024-03-12 00:57:55

Em um sistema que estava desenvolvendo me deparei com a seguinte demanda, ler um arquivo csv e devolver seu primeiro resultado para analise, um arquivo csv podem vir com a primeira linha sendo um cabeçalho, logo essa linha deve ser ignorada e a segunda linha deve ser retornada ao invés da primeira.

O codigo para essa tarefa é simples.

```php
public function getFirstContent(string $filename, UploadedFile $file, bool $hasHeader = false): array
    {
        $openFile = $file->openFile();
        $csv = [];
        while (($row = $openFile->fgets()) !== false) {
            if ($hasHeader) {
                continue;
            }
            $csv = str_getcsv($row);
            break;
        }
        $openFile = null;
        $file->storeAs(self::SAVE_DIR, $filename);

        return $csv;
    }
```


Você pode ter notado o erro desta implementação, eu não. Após terminar de fazer esse código fui fazer os testes desta função. Escrevi testes com um caso onde o csv não teria um cabeçalho e o outro teria um cabeçalho, um teste deveria chamar a função `fgets` uma vez e outro duas, eis o codigo do teste

```php
/**
     * @dataProvider cases
     */
    public function testGetFistContent(bool $hasHeader, array $fgets, string $expected): void
    {
        // arrange
        $splFileMock = $this->getMockBuilder(SplFileObject::class)
                            ->setConstructorArgs(['php://memory'])
                        ->getMock();
        $splFileMock->expects($this->exactly(count($fgets)))->method('fgets')->willReturnOnConsecutiveCalls(...$fgets);

        $file = $this->createMock(UploadedFile::class);
        $file->expects($this->once())->method('openFile')->willReturn($splFileMock);
        $file->expects($this->once())->method('storeAs')->with('/tmp', 'file.csv');

        // act
        $result = $this->service->getFirstContent('file.csv', $file, $hasHeader);

        // assert
        $this->assertIsArray($result);
        $this->assertSame($expected, $result[0]);
    }

public function cases(): array
    {
        return [
            [false, ['a,b,c'], 'a'],
            [true, ['a,b,c', 'c,b,a'], 'c']
        ];
    }
```

O primeiro teste rodou de forma correta e passou, o segundo caso, onde o cabeçalho existe e deve ser pulada não estava passando, justamente porque `$hasHeader` nunca muda seu estado, logo quando for `true`, sempre irá pular a linha e nunca lerá o csv, um erro simples, fácil de ser corrigido, porém com um alto potencial de quebrar sistemas, imagine o quando de processamento desnecessário um loop infinito irá gerar?

Ao notar isso adicionei a uma linha de correção, um simples `$hasHeader = false` e pronto, o teste passou.

```php
while (($row = $openFile->fgets()) !== false) {
            if ($hasHeader) {
                $hasHeader = false;
                continue;
            }
            $csv = str_getcsv($row);
            break;
}
```

Testes são importantes para prevenir erros de falta de atenção, que podem ocorrer quando estamos com um prazo apertado ou no dia em que não estamos muito inspirados.

Sempre teste seu código, até mais!