O labgrid é uma ferramenta de abstração de hardware, com foco em teste, desenvolvimento e automação em geral. Pode ser utilizada como uma CLI para comandar um sistema, como uma ferramenta para scripts (bibliotecas em python) ou como ferramenta de testes (integrado ao pytest). Ele é bastante eficaz quando se trata de testes em sistemas Linux embarcado. Neste artigo, o labgrid será instalado num host, e acessará um target via serial.
Vale lembrar que o labgrid não é um framework de teste por si só, mas é feito pra ser combinado com o pytest e seus plugins.
Os testes aqui realizados foram baseados na documentação oficial do labgrid [1], mais especificamente na documentação de uso [2].
Instalação do labgrid
O labgrid é facilmente instalado por meio do pip, conforme a seguir. Para o que será realizado no presente artigo, basta instalá-lo em um host Linux, não sendo necessário a instalação na máquina target.
```sh
pip install labgrid
```
labgrid como biblioteca
Um sistema é representado como um Target. Um target costuma possuir Resources (recursos) e Drivers. Em casos que a placa precisa de uma transição (ex.: off no Bootloader), pode ser necessário uma Strategy (estratégia). Aqui serão explorados apenas Resources e Drivers.
Exemplos de Drivers [3]: SSHDriver, CommandProtocol, GpioDigitalOutputDriver, etc.
Exemplos de Resources [4]: NetworkService, RawSerialPort, SysfsGPIO, etc.
Teste com acesso remoto via porta serial
A biblioteca do labgrid oferece duas maneiras de configurar targets com resources e drivers: criar o Target diretamente ou usar o Environment (ambiente) para carregar um arquivo de configuração (.yaml).
```yaml
targets:
main:
resources:
RawSerialPort:
port: "/dev/ttyUSB0"
drivers:
SerialDriver: {}
ShellDriver:
login_timeout: 75
prompt: '# '
login_prompt: 'login: '
username: 'root'
password: 'sua senha'
target2:
resources:
resource1:
arg1: 'ex'
drivers:
drv1: {}
drv2:
arg1: 'ex1'
arg2: 123
```
No exemplo do acima é usado um arquivo local.yaml para configurar o ambiente, e ele é chamado usando o argumento --lg-env local.yaml no comando do pytest (usando por padrão o target main).
O campo "targets: main: resources: RawSerialPort" possui as informações da serial, e deve ser preenchido com o caminho para a porta serial adequada do host. Outro parâmetro que pode ser preenchido é o valor de baud rate, com o parâmetro "speed", cujo valor padrão é 115200 bps, sendo opcional para esta aplicação.
O campo "targets: main: drivers" possui configurações dos drivers necessários para o teste que será realizado, neste caso, o "SerialDriver" e o "ShellDriver". As configurações do "ShellDriver" são o tempo máximo para realizar o login em segundos (login_timeout), o texto do prompt de comando (neste caso, o texto é "# "), o texto do prompt de login (login_prompt), o usuário e a senha de login ("root" e "sua senha", respectivamente).
A inicialização do ambiente e do target é feita em uma fixture do pytest. Se desejar, é possível remover o argumento --lg-env local.yaml do comando do pytest, criando um objeto pro ambiente e pro target direto de dentro da fixture command. Considere esta fixture dentro do módulo conftest.py, que será executada antes da módulo de teste. As duas opções podem ser vistas a seguir:
Com ambiente por comando do pytest:
```python
import pytest
@pytest.fixture(scope='session')
def command(target):
# target padrão = main
shell = target.get_driver('CommandProtocol')
target.activate(shell)
return shell
```
Com ambiente por código:
```python
import pytest
from labgrid import Environment
@pytest.fixture(scope='session')
def command():
env = Environment('local.yaml')
target = env.get_target('main')
shell = target.get_driver('CommandProtocol')
target.activate(shell)
return shell
```
Por fim, basta usar os recursos configurados em um módulo python (neste caso, test_shell.py):
```python
def test_shell(command):
stdout, stderr, returncode = command.run('cat /proc/version')
assert returncode == 0
assert stdout
assert not stderr
assert 'Linux' in stdout[0]
stdout, stderr, returncode = command.run('false')
assert returncode != 0
assert not stdout
assert not stderr
```
Para executar o teste, a partir da máquina de host, deve-se usar um dos dois comandos:
```shell
# com ambiente por comando do pytest
pytest --lg-env local.yaml test_shell.py
# com ambiente por codigo
pytest test_shell.py
```
Inicializando o target com o console externado em uma porta serial conectada ao host, a seguinte mensagem deverá ser mostrada logo após a inicialização e realização do teste:
```shell
========================================== test session starts ==========================================
platform linux -- Python 3.8.10, pytest-7.2.2, pluggy-1.2.0
rootdir: /home/matheusaguiar/Projetos/labgridtest/test/shell
plugins: labgrid-23.0.3
collected 1 item
test_shell.py . [100%]
=========================================== 1 passed in 2.31s ===========================================
```
Com poucas modificações é possível configurar a conexão para ser feita via ssh, utilizando o mesmo módulo de teste test_shell.py.
Na configuração do ambiente, no arquivo local.yaml:
```yaml
targets:
main:
resources:
NetworkService:
address: '192.168.0.1'
name: 'board_network'
username: 'root'
password: 'sua senha'
drivers:
SSHDriver: {}
```
O campo "targets: main: resources: NetworkService: address:" deve conter o endereço IP do target.
No arquivo conftest.py, que possui a fixture command:
```python
import pytest
@pytest.fixture(scope='session')
def command(target):
ssh = target.get_driver('SSHDriver')
return ssh
```
Assim como no caso do teste via serial, os comandos realizados dependem de como foi configurado o target, sendo um ponto que merece atenção.
Referências:
[2] Uso do labgrid
[3] Drivers padrão
[4] Recursos padrão