Skip to main content

autestoy is a Python toy library for automating tests. autestoy -> auto test toy

Project description

简介

一个尝试用于特定场景的不专业(指作者)的原型验证自动化测试工具

名称一拍脑袋 auto+test+toy

处于早早早早期阶段

设计理念

  • 协议支持保持可移植性,不应引入具体的细节支持,例如支持特定产品
  • 考虑到使用环境,数据类切片应靠近verilog语法

项目结构

目前的src树

src
├── autestoy
│   ├── __init__.py       # 暴露API   ├── export            # 导出相关功能源码目录      ├── collect.py        # 收集器,用于记录的收集      ├── obsidian.py       # obsidian格式(markdown+mermaid)生成器      ├── pdf.py            # pdf报告生成器      ├── term.py           # 终端显示、样式、时间戳配置      └── web.py            # web报告生成器,暂定niegui   ├── protocols         # 测试通路协议相关源码目录      ├── jtag.py           # jtag通路,作者相关知识储备较少,优先级降低      ├── serial.py         # 串口连接      ├── ssh.py            # ssh、sftp      └── telnet.py         # telnet协议连接   └── tools             # 工具源码目录       ├── ansi.py           # 终端显示ansi转义       ├── datatype.py       # 数据类,创建易于操作的寄存器值以及数据转换       ├── record.py         # 定义记录类,用于处理与报告生成       ├── result.py         # 定义协议返回的结果       └── timestamp.py      # 定义时间戳工具
...

未来规划

  • 尽快完善基础功能,至少完成一条完整的测试-显示-导出报告的流程
  • 多环境测试

畅想(coding过程中的灵光一动)

  • 实现字段类,将寄存器拆为多个字段直接控制
  • 元编程,实时处理

快速开始

ssh

exec_run

import autestoy as att
conf = att.RemoteConfig(user='root',ip='xxx.xxx.xxx.xxx',password='xxxx').set_name('DUT') # 配置remote
dut = att.SSH(conf) # 连接ssh
# 对一条指令的结果进行处理
record = dut.exec_run('ls')
if 'log.txt' in record: 
    do_something()

long_running

import autestoy as att
conf = att.RemoteConfig(user='root',ip='xxx.xxx.xxx.xxx',password='xxxx').set_name('DUT') # 配置remote
dut = att.SSH(conf) # 连接ssh
# 对持续运行的指令进行处理
record = dut.long_running('tail -f log.txt') # 非阻塞运行
dut.exec_run('./create_log.sh') 

ts = att.TrySeconds(10)
while ts:
    if res:=record.search_next_line(r'fail\s+at\s+(\d+:\d+)'): 
        # 例如fifo获取字符串"[LOG] fail at 12:04 !" 会匹配:
        # res.group(0)="fail at 12:04"
        # res.group(1)="12:04"
        ulog('found script error at:',res.group(1)) 
        break

record.task_kill()
assert not record.long_running_task.is_alive()    

具体细节

(想到哪写到哪)

protocols

ssh

class SSH

  • SSH

SSH实现了两套方法,一种是基于ssh连接的exec_run,每运行一次会创建一个通道,运行结束后销毁,所以无法保持上下文、路径等,运行效率稍低,但方便处理;

remote_config = RemoteConfig(...)
dut = SSH(remote_config)
dut.exec_run('cd path') # 每次exec_run都会创建一个新的通道,因此这条cd命令只在此次命令中有效
# home/path/
dut.exec_run('pwd') # 再次运行pwd目录恢复到创建channel时的默认路径
# home
dut.set_globel_path('./path') # global_path是类内部维护的一个全局路径,等同于在所有命令前加入cd命令
dut.exec_run('pwd') # 等同于 "cd ./path && pwd"
# home/path/
dut.with_path('home/another_path/').exec_run('pwd') # with_path会设置一个只能执行一次的临时路径,使用exec_run后消失
# /home/another_path
dut.exec_run('pwd')
# /home/path
dut.cd('new_path') # cd方法作用于global_path,切换全局路径
dut.exec_run('pwd')
# /home/path/new_path

还实现了long_running即长时间后台运行命令,通过threading库实现多线程运行,以达成不阻塞后续命令运行的效果。使用fifo在进程间传递命令的输出,可以做到实时处理输出特征。

remote_config = RemoteConfig(...)
dut = SSH(remote_config)
process = dut.long_running('python create_log.py') # 设想这是一条可以持续产生log的脚本
tail_res = dut.long_running('tail -f log.txt') # 实时显示log输出
# 粗糙的处理流程,待改进
try_10s = TrySeconds(10)
while try_10s: # 10s后退出
    if tail_res.search_next_line('fail'): # fifo非空且'fail' 在fifo中,则退出
        break
# 杀死进程:内部先使用stdin发送ctrl-c给远程退出信号,再运行td.Event.set()结束本地线程。
process.task_kill()
tail_res.task_kill()
# 查看进程状态,如果命令阻塞可能无法响应td.Event事件
print(process.long_running_task.is_alive())
print(tail_res.long_running_task.is_alive())

另一种是基于channel的交互式run方法,所有命令基于一个channel,可以保持上下文,效率高,但是处理复杂,需要自行识别命令行提示符号,不支持花里胡哨的命令行提示符。

channel的处理逻辑是根据正则表达式捕获命令行提示符,如果命令输出刚好匹配到了该正则,会导致输出处理提前结束,并影响后续命令。目前没有很好的解决方法。

remote_config = RemoteConfig(...)
dut = SSH(remote_config)
dut_ch1 = dut.create_channel() 
# 如果远程环境使用了花里胡哨的终端,例如zsh {    ~/Project/autestoy ... ✔  autestoy  }这样子的提示符,并且在初始化channel时卡处
# 可以尝试设置insert_cmd参数,将在自动匹配终端提示符前发送一条命令
# 例如 ch1 = dut.create_channel(insert_cmd="bash"),这将切换为bash环境
dut_ch1.run('pwd')
# home
dut_ch1.run('cd path') # 在同一channel中运行,上下文继承
dut_ch1.run('pwd') 
# home/path

基于channel的实现无long_running方法,实现long_running即会占用该通道,不如直接创建新通道运行。

  • 关于term输出的时间戳

时间戳大部分在获取返回内容并处理完成后输出时添加,所以并不代表命令输出的实际精确时间。但也可以一定程度上反映多线程语句输出的前后关系。

tools

datatype

class Bits

  • 创建Bits:

Bits是为可以快速创建和修改特定位的数据类。以特定的切片格式快速访问和修改单个bit或bit字段。

  1. 从int创建:

int无法反映数据宽度,必须指定width参数

reg = Bits( 65535  , 16 ) # 0xFFFF      16bits
reg = Bits( 0x1234 , 8  ) # 0x34         8bits :发生高位截断
reg = Bits( 0b1111 , 32 ) # 0x0000_000F 32bits :高位补0
  1. 从str创建:

带有位数标识的字符串可以省略width,也可以使用width重新指定宽度;

没有位数标识的字符串必须指定width;

reg = Bits( "0x1234_u8"     ) # 0x34         8bits :字符串解析也会造成截断
reg = Bits( "0x1234_i8" , 16) # 0x0034      16bits :width指定宽度在字符串解析后作用,因此这种写法会并不会防止截断
reg = Bits( "0x1234"    , 32) # 0x0000_1234 32bits :字符串无宽度标识时,需要指定宽度
reg = Bits( "8'hFF"     , 8 ) # 0xFF         8bits :str支持verilog近似的语法,分隔副使用英文单引号,因此字符串使用双引号括起
reg = Bits( "32'hDEADBEAF"  ) # 0xDEAD_BEAF 32bits :当然可以省略width
reg = Bits( "2.5E4"     , 16) # 2500        16bits :科学计数法解析结果为float的字符串如果转换为int值不变,也可以被Bits接受
reg = Bits( "3.0E2_u8"      ) # 0x2C         8bits :也支持科学计数法+标注位数,可以不指定width,当然也受到截断影响

目前"u8"、"i8"等有符号/无符号标识没有作区别处理。

  1. 从可迭代对象创建:

可迭代对象的子类型可以是任意上述创建方法,需要指定宽度的传入元组携带参数,返回所有对象的拼接Bits

reg = Bits([ "8'hFF" , (0xAB,8) , ("255",8) , "0b0001_0010_i8"])
# reg -> 0xFFAB_FF12 32bits , 
  • Bits切片:

Bits切片遵循类似verilog的语法。

  1. Bits[n] 返回单比特,默认右侧低位
reg = Bits(0b0001_0000 , 8)
reg[3]  -> Bits(0b0,1) # 默认右侧低位,第4位
reg[3:] -> Bits(0b0,1) # 指定右侧低位,第4位
reg[:3] -> Bits(0b1,1) # 指定左侧低位,第4位
  1. Bits[a:b] a>b 右侧为低位 ; a<b 左侧为低位
reg = Bits( 0x1234_5678 , 32 )
reg[15:0] == res[16:31] == Bits( 0x5678 , 16 )
reg[0:15] == reg[31:16] == Bits( 0x1234 , 16 )
  1. Bits[ a:b , c ...] 混合切片拼接
reg = Bits( 0x1234_5678 , 32 )
# 单bit拼接
reg[ 3 , 2 , 1 , 0 ] == reg[ 3: , 2: , 1: , 0: ] == reg[3:0] == Bits( 0x8 , 4 )
# 切片拼接
reg[ 7:0 , 0:7] == Bits( 0x7812 , 16 )
# 混合拼接
reg[ :0 , 1:2 , :3 ] == reg[0:3] == Bits( 0x1 , 4 )

ToDoList

  • 为ssh-Channel.run/SSH.exec_run实现短交互命令,例如sudo登陆

  • ssh-SSH/Channel类初始化添加时间戳记录,考虑新的?Record类:MataRecord?

  • 为?Record类添加方便的取值方法

  • SSH、Channel、SFTP添加最近一次输出缓存

  • ?Reocrd类添加保存错误退出码的属性

  • ?Record添加正则匹配

  • 统一测试文件,运行时使用ftp传输运行脚本到远程被测试端,测试完成后删除

    • ftp服务
    • 添加CmdRecord,并作兼容处理->Result[T]
    • 两端文件hash校验
    • 获取远程服务器平台,可执行文件列表,hash命令
    • 本地hashlib实现文件校验
  • 记录每一行命令输出的时间戳

    • Result-CmdRecord、CmdRecording为每一行输出添加时间戳
    • 更改print函数->可拓展是否显示时间戳,更改样式
    • 实现Timestamp类,替代time.time()
  • 数据类-完善

    • np.array(uint8) 数据转换,bit切片转换 -> numpy引入处理复杂度,无极端速度需求,去除
    • Bits
    • 基础切片
    • 附加功能切片(还没想好)
    • 段赋值
    • Binary(Bits)
    • Hexadecimal(Bits)
    • Decimal(Bits)
    • Field(Bits):寄存器子字段Bits
    • Register(Bits+):带有字段的定长,
    • Packet(Bits):带有字段的数据包类
  • obsidian(markdiwn+mermaid) export

  • web export

  • pdf export

  • term display

  • BUG:ssh的channel模式run方法,概率性出现回显去除失败。

  • BUG:ssh-create_channel遇到zsh等进行了美化的终端时获取不到prompt死循环->嵌入bash

已知问题

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

autestoy-0.1.2.tar.gz (32.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

autestoy-0.1.2-py3-none-any.whl (32.2 kB view details)

Uploaded Python 3

File details

Details for the file autestoy-0.1.2.tar.gz.

File metadata

  • Download URL: autestoy-0.1.2.tar.gz
  • Upload date:
  • Size: 32.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Manjaro Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for autestoy-0.1.2.tar.gz
Algorithm Hash digest
SHA256 27165f8558ed7f52baee6fa589be56d69b2df4cb17c842eab7a3304bc6e51dce
MD5 c56aa8dd39c57d48a4b99f8dbecee71a
BLAKE2b-256 35dcd335ca85ef4368d40cc6ddddde59c31dec66f68e8236072b814cbad85b3d

See more details on using hashes here.

File details

Details for the file autestoy-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: autestoy-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 32.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.10 {"installer":{"name":"uv","version":"0.10.10","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Manjaro Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for autestoy-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f58342415ef6a781f3bc9efd371f1fe248044d46a2964888522f05544aa20b11
MD5 f78465261a8fbd036ea0dc643a845d31
BLAKE2b-256 143577b039b27c6c886630a9f476c1d05a459015bcfe058a0ff102f2703c3cef

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page