芯片测试程序版本管理:目录结构设计的四道坎
2026/9/6 9:53:22 网站建设 项目流程

接手旧测试程序的那天,我就知道这个“烂摊子”不好收拾。甲方给的加密驱动盘里装着一个跑了几年的芯片测试程序,目录里密密麻麻堆了三四层文件夹,名字从“FINAL_v2”到“FINAL_v3_real”,再到“final_new_2024”…文件混着测试数据、日志、临时改的.bin、机台上导出的.csv,还有好几个不知道干嘛用的旧配置。最让人崩溃的是,程序里每个测试项对应的限值文件散落在不同子目录,换一台机型就得手动改路径。机器上跑的版本和页面里保存的版本,根本对不上。

那次之后我花了大半年,把手里所有芯片测试程序包全部重构成了公司内部的标准化目录,顺手把版本管理也彻底理顺了。这个“(二)”,我想专门聊聊目录结构这件事。芯片测试程序要做版本管理,第一关从来不是学会几条git命令,而是先把目录结构设计清楚。一台ATE上跑的测试程序,动辄几百个文件,测试项、限值、校准文件、机台配置、数据采集脚本全都挤在一起。目录结构如果一开始就是乱的,后面无论你用多好的版本管理工具,都只能把混乱备份得更好一点而已。

目录结构这件事,我总结下来要过四道坎。这四道坎看起来都不起眼,但每一道都决定了你的版本库能不能长期健康地活下来。

1. 第一道坎:顶层目录按产品线划分,还是按测试平台划分

很多测试工程师第一次搭目录结构时,纠结的本质就一句话:最上层这一级,到底放产品型号,还是放测试平台?

如果你是做定制芯片的,一个型号对应一条产品线,测试程序基本只在一种平台上跑,那按产品线划分会很直观,目录顶层就是产品型号,里面再放需要的东西。但问题是,芯片公司通常不会这么简单。同一个产品可能有多个量产节点,不同节点又可能用不同厂商的ATE,甚至同一款芯片会从开发验证阶段的实验室机台,转到量产阶段的量产机台。这时候最上层的划分逻辑一旦选错,整个目录就非常别扭。按平台划分,你会发现同一个产品的程序散落在好几个平台目录下,做版本管理时根本没法把一个产品的完整程序一次性打成一个基线;按产品划分,平台相关的公共配置又会在不同产品目录里重复出现,改一处忘一处。

两种方案我都不打算直接否定,我推荐的做法是“产品线优先,平台作为第二级分支”:

  • 第一级固定为产品线或产品型号,这是所有版本管理、项目代号、评审编号的统一入口。
  • 第二级固定为测试平台或测试方案,程序相关的源码、工程文件放这个层级。
  • 第三级才是功能模块,比如source、spec、config、data、release这一层。

这种结构的核心思路是:产品线是相对稳定的业务实体,而测试平台的更换、升级、并存,只是产品生命周期里的一个变量。代码、数据可以跟着平台变,但产品线这个锚点不能变。版本库里的主干、标签、分支,都围绕产品线来组织,平台差异只体现在子目录中。实际跑下来,你会发现在做release包、做客户交付、做跨部门协作时,这个顶层非常省事。

1.1 两种顶层划分方案的利弊对照

我先用一个表把两种方案的真实感受列出来,很多细节是踩过坑才看得见的:

维度按产品线划分(推荐)按测试平台划分
版本基线完整性一个产品一个仓库目录,基线清晰产品程序散落多平台,基线难定义
平台升级影响平台升级只影响对应二级目录,可单独升级顶层目录就需要整体重构
跨产品复用共享代码需单独建公共仓库,管理略复杂平台公共库天然集中,复用方便
新项目启动复制产品模板即可,上手快按平台入口找东西,但产品内聚性弱
多项目中后期长期维护友好,release追溯容易换平台时方案越用越乱

如果你的公司测试平台非常统一,所有产品都用同一种机台,那按平台划分短期内也能跑,还算顺手。但只要产品一多,你会遇到一个特别尴尬的场景:同一款产品在研发阶段和量产阶段用的机台不一样,两边程序都要维护,你在平台目录下再按产品分,还是在产品目录里再按平台分,怎么分都很别扭。所以我还是建议一开始就按产品线划分,把平台差异降为第二级子目录。

1.2 我建议的顶层目录实例

直接给一个我已经用了两年、目前还比较舒服的目录骨架示例:

Product_A/ # 产品线,版本库根目录 ├── src/ # 测试程序源码,跟随版本管理 │ ├── common/ # 产品内公共代码、复用函数 │ ├── platform_advantest/ # 指定平台的测试程序工程 │ │ ├── testsuite/ # 测试项序列 │ │ ├── testmethod/ # 测试方法封装 │ │ └── device_interface/ # 设备接口层 │ └── platform_teradyne/ # 另一平台的测试程序工程 ├── spec/ # 测试规格、限值文档 ├── config/ # 机台配置、校准参数模板 ├── data/ # 测试数据、日志(不入库,见第二道坎) ├── release/ # 已发布版本归档 │ ├── v1.2.0/ │ └── v1.3.0/ └── docs/ # 设计文档、变更说明

这套结构的关键点有两个。一是该产品线内所有平台的测试程序都放在同一个版本库里,编程序、做测试、写文档的人永远从同一个入口进场。二是release目录保留了“发布快照”,每个版本对应一份可追溯的归档,这比在git里翻历史标签更直观,尤其是当现场需要紧急回退时,可以直接把历史版本拷到机台上,不用重新拉代码再编译。

我当时把所有库迁移到这个结构之后,最大的感受是:讨论问题的时候不再说“那个文件在某某机台的某某目录下”,而是直接说“A产品线的spec里”。版本管理也是一样,打tag、开分支、做审查,全都在一个库里完成,省掉了跨库关联的无数沟通成本。

2. 第二道坎:程序文件和数据文件,哪些该进仓库

目录结构确定之后,第二个常见问题就是:版本库里一片混乱,什么文件都往里塞。

芯片测试程序有个特点,每天跑完测试都会产生大量现场数据——这包括stdf、dat、csv、日志文件、机台自动保存的备份文件、临时生成的波形图、良率汇总等。这些东西如果和测试程序源码放一起,并且一股脑提交到版本库里,两三个版本之后,仓库体积就会膨胀到不可收拾。提交历史里夹杂着一堆几MB甚至几十MB的数据文件,clone一次仓库慢得像下电影,diff查看代码变更时也被大量二进制数据干扰。

这里面的边界,很多人其实不是不知道,而是没有坚决执行。我的原则就三条:

  1. 能自动再次生成的文件,一律不进版本库。
  2. 数据文件和源文件必须物理隔离,即使都在本地目录里,也要分别放在data、log和src、config下。
  3. 为应付审计或追溯而需要保留的数据,进独立的存储系统或免密带库,绝不进代码仓库。

2.1 一份“干净”的测试程序包由哪些文件组成

我做过一个内部培训,列过一张“测试程序包文件清单”。这里直接分享出来,可以作为初筛的依据:

类别进版本库?典型文件
测试源码testmethod、testsuite、UI定义、工程文件
公共库代码common函数、API封装、基础库
测试规格/限值文档spec文档、limit模板
机台配置模板配置文件、参数文件、默认模板
校准参数是(需版本管理)校准文件、Setup文件
测试记录的原始数据stdf、dat、日志、波形文件
临时脚本/中间产物临时修复用脚本、生成的临时文件
发布包归档release目录下的正式版本压缩包

校准参数这条很多人会犹豫,觉得它跟现场机台强相关,不该入库。我的看法是:校准参数恰恰是最需要版本管理的,因为芯片测试现场经常出现“同一条线,不同批次校准完结果不一样”的情况。把校准参数做成一个带版本、带生效日期的文件入库,出现问题就可以快速回溯是不是校准参数变化导致的。但注意,入库的是校准参数的“模板和配置”,而非每批实时产生的校准曲线数据,那些实时数据还是走数据存储。

2.2 .gitignore 的实战配置

如果说清点文件是目录结构设计的一部分,那落地就靠.gitignore。Git本身不会主动忽略任何文件,你不写规则,它就把所有文件都当作跟踪对象。下面是我通常在芯片测试程序仓库里使用的.gitignore模板,你可以直接裁剪使用:

# 数据与日志 *.stdf *.dat *.csv *.log *.txt.bak # 机台自动备份文件 *.bak *.tmp *.swp # 本地临时文件 temp/ tmp/ *.pyc __pycache__/ # 系统/工具生成 .DS_Store Thumbs.db .idea/ .vscode/

这里有个细节很多人会忽略:测试程序目录里经常有“机台会主动生成”的目录结构,比如泰瑞达机台自动生成的tmid、日志目录,爱德万测试台生成的result目录等。一定要提前观察清楚,在.gitignore里一并忽略,否则每次一跑测试,git status就会一片红,干扰你判断真正的变更。

另一个值得注意的点是:.gitignore只对“尚未被跟踪”的文件生效。如果一开始就误把数据文件提交进去了,后面再加ignore是拦不住的,必须先git rm --cached把文件从索引移除。这也是我为什么反复强调:目录设计要在一开始就做对,补课永远比欠课痛苦。

2.3 大文件与二进制文件的处理思路

芯片测试程序仓库里,总有那么几个无论如何都要提交、但又奇大无比的文件,比如某些加密的测试向量文件、仿真模型、特定平台下的库文件。这种文件用普通git管理会越来越痛苦。我的经验是:能拆则拆,不能拆就单独用Git LFS管理。

Git LFS的思路很简单,把大文件用指针替换入库,实际内容存到LFS存储。本地clone时自动拉取必要文件,仓库本身不会无限膨胀。如果你还在用老的git大文件管理模式,仓库体积已经大到每改一行代码都要等半天,那我建议尽早迁移到LFS。向团队推LFS时尽量把门槛降低,直接在仓库根目录加一个.lfsconfig文件,把LFS的URL固定好,新人拉下来就能用。

3. 第三道坎:公共代码库的归属问题

芯片测试程序里总有这么一块代码:负责和机台通信的低层封装,通用的开关矩阵驱动,数据处理函数库,甚至工程师自己写的一套“私房工具集”。这类公共代码,很多项目都处理不好。处理不好就出现两种极端。一种是“人人自建”,每个产品线都拷贝一份公共代码到自己目录下,结果公共代码里修了一个bug,其他产品线完全不知情,继续用着有bug的旧版,最后在产品表现上栽了跟头;另一种是“人人共建”,看着是公共目录,其实谁都能改,改坏了所有产品线一起遭殃,最后公共代码变成“谁都不敢动”的重灾区。

这个问题的本质,是要把“复用”和“变更控制”这两件事分开。复用是为了提高效率,变更控制是为了保证稳定。公共代码的维护者不能是所有使用者,而应该是少数几个有权限的负责人。

3.1 公共代码的两种管理模式对比

IC测试程序的公共代码管理,我实际见过两种比较靠谱的模式:

模式一:公共代码独立仓库,各产品线通过子模块引用。这种模式用git submodule把公共仓库挂到产品线仓库的某个目录下。好处是公共代码的版本管理很干净,产品线锁定了一个特定的公共代码commit,不会因为公共库更新而意外变化;坏处是submodule的操作学习曲线陡峭,新人经常忘记在拉取产品线仓库后同步子模块,结果编译时用旧代码,排查半天都发现不了。如果你团队的git水平参差不齐,这个模式推行成本很高。

模式二:公共代码独立仓库,产品线仓库通过自动化脚本在构建时拉取指定tag。这种模式名义上也是独立仓库,但不引入submodule的复杂度。测试程序编译前执行一个脚本,从公共仓库拉取特定版本的代码到本地工作目录。我目前在团队里用的就是这种,每天CI构建时自动拉最新稳定tag,总比团队成员手动同步靠谱。

对比下来,我的态度很明确:如果你有专职的自动化构建环境,上模式二;如果你们还是以本地手动编译为主,那模式一虽然麻烦,但至少可控。

3.2 公共代码仓库的目录设计

公共库内部也要分目录,不能一锅粥。我维护的公共代码仓库目录大致是这样的:

common_libs/ ├── api/ # 机台API封装层 ├── utils/ # 数据处理工具函数 ├── drivers/ # 仪表/探针台等驱动封装 ├── templates/ # 测试项模板、规范模板 └── docs/ # 引用说明、版本变更说明

公共代码的目录设计原则和产品线仓库不太一样,这里更强调“按功能分层”,而不是“按项目组织”。因为公共代码的消费者是各个项目,按项目分会造成同一个公共函数有多个拷贝,失去公共库的意义。按功能分层,每个功能模块内部再维护自己的变更历史,使用者只需要关注自己用到的那部分API版本。

这里还有一个小的经验补充:公共代码库一定要维护一个CHANGELOG,每次变更都要写清楚改了什么、影响哪些产品线、是否有破坏性变化。否则用产品线的人根本不知道公共库又更新了什么,只能盲目升级,升级完测试结果不对也无法定位。公共代码的变更说明,重要性不亚于代码本身。

4. 第四道坎:配置文件漂移带来的版本错乱

前面三道坎解决的是“放哪里”“哪些进库”的问题。配置文件的坑在于:它的变化往往非常隐蔽,改了之后不一定会立即报错,只会让测试结果在某个边界条件下悄悄漂移。

芯片测试程序里,配置文件很多,常见的有:

  • 测试限值文件(spec/limit文件),定义了每一项测试的上下限;
  • 机台配置参数(如测试电压、电流量程、时序参数);
  • 校准文件和校准系数;
  • Bin表映射(测试结果分Bin的定义);
  • 探针台、分选机通信参数。

其中最容易出问题的就是测试限值文件和校准系数。限值文件被谁在某天随手改了一个数值,跑出来的良率立刻变好,大家还挺高兴,量产几天后客户反馈有bad chip流出,最后追查才发现是限值被改宽了。这种事故在芯片测试行业不是个别案例。版本管理能把变更记录下来,但它解决不了“文件被改而不自知”的问题。要解决,得从配置文件的生成和校验机制入手。

4.1 配置文件的典型踩坑场景

我见过最典型的场景是这样的:量产线上某个产品的测试程序,限值文件是直接在机台上打开手动编辑的。某天夜班工程师觉得某个测试项良率偏低,顺手把下限从80改成了75,保存,关掉。第二天早班的高工发现测试程序跑出来的良率正常,以为是产线优化了,就没有深究。三天后,出货抽检发现一颗边界芯片没过系统级测试,追查下来发现就是那个限值改动导致的。配置文件在版本管理里确实留下了变更记录,但问题在于它没有经过任何审批流程,没有和“测试条件变更单”关联,也没有在启动时做版本一致性检查。

这个问题的根子,在于配置文件和测试程序本身是“离线的”:程序跑起来就读取本目录下的配置文件,它无法判断这个文件是不是当前版本应该使用的文件。解决思路是说通俗点,让“程序能自己识别配置文件的合法性”。

4.2 配置文件的生成、校验与下发机制

我推荐的机制是三层:

第一层:配置模板进版本库,作为唯一事实源。所有限值、参数模板都由负责人维护,入库并打tag。任何人不得在机台上直接编辑最终配置文件。

第二层:通过脚本从模板生成实际配置文件,自动加上版本号、生成时间和哈希值。生成的配置文件也进版本库(但由于是生成物,体积小,入库没有问题),或者作为release的一部分归档。这样做的好处是,现场用的每一个配置文件都可以直接追溯到某个模板版本。

第三层:测试程序在启动时执行配置校验,读取配置文件中的版本信息和哈希值,如果版本不在允许的范围内,直接拒绝启动并报错。这一步非常关键,它确保机器上跑的程序一定是和当前产品基线匹配的版本。

下面是一个简化的Python校验思路,通常在ATE测试主程序初始化阶段调用:

import hashlib import json def verify_config(config_path, expected_version): with open(config_path, "r") as f: config = json.load(f) if config["version"] != expected_version: raise RuntimeError(f"Config version mismatch: expect {expected_version}, got {config['version']}") actual_hash = hashlib.sha256( open(config_path, "rb").read() ).hexdigest() if actual_hash != config["sha256"]: raise RuntimeError("Config file is tampered or corrupted.") print("Config verify PASS.")

实际项目中你可能会在ATE测试项初始化的C语言或Java代码里做同样的事,核心不变:配置文件必须自带身份信息,程序在运行前必须校验。能做到这一点,配置文件的“漂移”问题就算真正堵住了。

5. 版本管理的日常操作:用 PyCharm 走通 SSH 链路

目录结构设计好了,配置文件机制也加了,日常的版本管理操作才能真正落下来。这里我必须提一个很多人问过的问题:如何在PyCharm里用SSH登录GitHub进行版本管理?芯片测试工程师很多人用PyCharm来写测试代码,但git操作经常还停留在网页端提交、本地命令行拉取的阶段。SSH配置好了以后,你会发现用IDE做代码审查、提交、合并,流畅度完全不一样。

5.1 为什么用SSH而不是HTTPS

芯片测试程序的代码仓库通常涉及商业保密。用HTTPS连接GitHub,每次push都要输入用户名和token,虽然有各种凭证管理器可以记住,但在ATE控制器这种不能随便安装软件、网络策略又严格的机器上,很容易出幺蛾子。SSH协议用密钥对做身份认证,配置好后不用每次输密码,也不依赖本地凭证管理器,遇到网络代理也更稳定。

实测下来,SSH方式还有一个好处:你可以把自己的私钥放在专门的安全目录里,配合密码保护,安全性比HTTPS token放在全局配置里要高一些。至少不会出现同事共用一台机台时,不小心把token配置带出去的情况。

5.2 从生成密钥到推送分支的完整流程

我这里给一份当前主流的操作流程,基于Windows或Linux都可以,macOS也适用。

第一步,在本地生成SSH密钥对。打开终端,执行:

ssh-keygen -t ed25519 -C "your_email@example.com"

建议一路回车使用默认路径,比如~/.ssh/id_ed25519。如果你的测试环境有特殊安全要求,也可以自定义密钥文件名,但后续配置要对应起来。生成的密钥对中,带.pub后缀的是公钥,可以给别人看;不带后缀的是私钥,绝对不能泄露。

第二步,把公钥添加到GitHub账号。在本地执行:

cat ~/.ssh/id_ed25519.pub

复制输出的内容,到GitHub页面Settings -> SSH and GPG keys -> New SSH key,粘贴保存。名字随意,比如 “ATE-lab-machine”。

第三步,在PyCharm里配置SSH。打开PyCharm,进入Settings/Settings -> Version Control -> Git,确认SSH executable选择“Native”或“Built-in”。Native会调用系统ssh命令,Built-in则用PyCharm自带的实现,两种都可以,但如果你本地自定义了~/.ssh/config,选Native更保险。配置完成后,回到PyCharm的欢迎页或VCS菜单,选择“Clone Repository”,把仓库的SSH地址复制进去,比如git@github.com:yourcompany/yourtest.git,输入仓库本地路径,克隆下来。

第四步,验证连接。最稳的方法是在终端执行:

ssh -T git@github.com

看到类似“Hi yourname! You've successfully authenticated”的提示,说明SSH链路已经通了。接下来你在PyCharm里做pull、push、fetch都不会再弹密码框。如果要推送到自己创建的分支,直接在PyCharm右下角的分支菜单里新建分支,提交后推送,第一次推送需要选择“Push”并确认设置上游分支即可。

5.3 日常协作:分支、合并、冲突处理

目录结构设计解决的是“文件放在哪里”,SSH解决的是“版本库怎么连”,但真正让版本管理运转起来的,是规范的协作流程。

我的建议是,长期维护的产品线仓库使用简化版Git Flow:main分支永远保持可发布状态,develop分支是日常集成分支,每个功能或修复任务从develop拉一个feature/xxx分支。开发完成后,通过PyCharm的Merge Request或直接在本地合并,再推到远端。对于芯片测试程序这类需要频繁跑机台验证的项目,分支数量不需要太多,多了反而乱。

真正容易出现问题的场景是合并冲突。在PyCharm里,冲突文件会红色高亮,右键选择“Resolve Conflicts”,可以手动对比左右两侧内容。芯片测试程序最容易冲突的文件就是配置文件、限值文件和测试项序列文件。为了减少这类冲突,我强烈建议:

  • 多人改同一文件时,遵循“按目录隔离”原则,你不要动我在做的测试项,我也不动你的配置文件;
  • 高频率把远端变更同步到本地,不要攒一个月的修改再一次性合并;
  • 配置文件一旦生成,尽量以自动脚本维护,不要手工改,避免冲突。

6. 常见问题与排查技巧实录

目录结构和版本管理实践过程中,我积累了不少“疑难杂症”的排查经验。挑一些高频问题列表整理出来,方便你直接对照处理。

6.1 目录结构类问题速查表

症状可能原因处理办法
每个工程师的目录结构都不一样没有统一的模板和规范制定目录模板,用脚手架脚本一键初始化
版本库文件越拉越慢,体积几十GB数据文件、日志误入库用Git LFS迁移大文件,把数据目录加入ignore
公共代码被误改,全产品线受影响公共目录没有变更控制公共代码独立仓库,限制写权限,走审批
程序在机台上找不到配置文件配置文件放在与程序分离的路径统一配置目录,程序启动时用相对路径定位
release目录越来越乱,无法判断哪个是正式版本没有版本命名规范使用v主版本.次版本.修订号,固定归档结构

这些问题里,最要命的是“每个工程师的目录结构都不一样”。这个问题的可怕之处在于,它会让版本管理的其他一切工作都变成无效投资。我在团队里做过一次插件化和标准化,把目录模板做成一个小工具,执行一条命令就能生成一个符合规范的项目骨架,最终逐步消灭了手工建目录的差异。

6.2 版本管理操作类问题速查表

症状可能原因处理办法
PyCharm Clone时提示Permission denied (publickey)SSH公钥未配置或私钥路径不对重新检查公钥是否已添加到GitHub,ssh-add确认密钥
提交后发现某个数据文件不想入库文件已经跟踪,用ignore已拦不住git rm --cached filename,再添加至.gitignore
合并时conflict太多,越解越乱分支长期未同步,多个改动交织先abort,再pull最新代码,重新基于最新分支修改
误删了本地更改,没有commit文件已被git跟踪,但改动丢失用Local History或IDE的本地历史恢复,极端情况用git fsck
测试程序在机台上无法回退到上一版本release没有归档,只有源代码建立release目录,每个正式版本打tag并归档压缩包

这里特别强调一下“误删本地更改”的恢复。PyCharm自带的Local History功能非常好用,哪怕你没有commit,只要文件在本地有历史版本,就能在右键菜单里打开Local History找到之前的版本。这个功能救过我好几次,建议所有用PyCharm写代码的工程师都养成习惯,重要改动在动手前先复制一份备份。

6.3 实操中容易忽略的几个细节

最后分享几个我踩过坑之后形成的固定习惯。

第一,提交信息必须写清楚“为什么”而不仅仅是“改了什么”。比如“修改open短路测试限值”就比“改limit文件”有用得多。版本管理的历史记录是给人看的,好的提交信息能让你三个月后翻记录时,一眼就明白当时的意图。

第二,测试程序的版本号和芯片硬件版本、测试软硬件配置最好打在一个统一的mindset里。也就是说,你的发布版本号不能只代表程序源码,还要能追溯到它适用于哪一批芯片的哪个设计版本、哪种校准配置。这样的话,现场反馈一个异常,你可以快速定位到底是硬件版本不匹配、程序版本落后,还是配置漂移。

第三,目录结构不是一成不变的,但变更要走“重命名”而不是“另建一套”。很多人觉得目录不好用,第一反应是重新建一套更好的目录,然后做拷贝迁移。这样做的后果是历史版本和旧目录完全脱节,版本管理彻底失效。正确的做法是在版本管理库内部执行目录重命名,让git记录追踪到文件历史,确保旧分支也能正确对应。

第四,在ATE机台上建议同时初始化好.gitignore和SSH配置。因为现场调试经常会在机台上直接改代码,如果机台上的环境没配置好,每次修改都没有版本记录,风险极大。我自己是每台常用机台都配好了开发环境、SSH密钥和git全局用户信息,目的就是让现场调试的行为也能被版本管理覆盖。

芯片测试程序的版本管理,说到底是一场和混乱作斗争的工程实践。目录结构就是这场斗争的主战场。四道坎,每一道都不是那种今天改完明天就见效的事,但只要坚持做下去,你会明显感觉到:项目交接不再靠一张嘴,release包不用再解压三遍找文件,出了异常不用再满机台翻旧文档。这种踏实的掌控感,是版本管理带给测试工程师最大的回报。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询