新闻详情

新闻详情

首页 / 资讯中心 / 详情

TestNG vs JUnit:自动化测试框架选型与工程实践指南

发布时间:2026/10/2 1:20:32来源:尧图网络
TestNG vs JUnit:自动化测试框架选型与工程实践指南
1. 从JUnit到TestNG为什么自动化测试团队最后都选了它做自动化测试这些年我见过太多团队在框架选型上反复横跳。一开始用JUnit跑通几个用例觉得挺爽等用例量上了三位数开始需要分组执行、依赖控制、并行跑批、数据驱动的时候JUnit 4那套机制就开始拧巴了。后来转TestNG很多问题属于是“换个角度突然就通了”。先给没接触过TestNG的人一个定位TestNG是一个受JUnit和TestNG早期版本启发的Java测试框架但它的设计目标从一开始就不是“再做一个JUnit”而是覆盖单元测试、集成测试、端到端测试的全场景需求。它的名字里的NG就是Next Generation的意思。我自己的体感是JUnit像一把精致的小刀适合精细雕刻TestNG更像一把瑞士军刀你未必每天用上所有功能但需要的时候它都在。1.1 测试框架的核心痛点不只是一个“能跑用例”的工具很多初学者以为测试框架就是“写个注解、点运行、看绿不绿”这是个特别大的误区。真实项目里测试框架要解决的是一连串工程问题用例组织和分类。几百上千条用例不可能全混在一起跑你得能按模块、按功能、按优先级灵活圈选。数据与逻辑分离。同一个登录流程要覆盖正常密码、错误密码、空密码、锁定账号等一堆场景不能每个场景复制一段代码。依赖与顺序控制。有些测试必须先登录再下单下单失败没必要继续跑支付。执行策略。除了快速跑全量回归还要支持指定分组、指定失败用例重跑、多线程并发提升效率。报告与反馈。跑了多少、挂了多少、挂在哪一步、耗时多少这些要一目了然最好还能集成到CI/CD流水线里。JUnit 4并不是不能做这些但很多能力是通过第三方扩展“补丁式”实现的。TestNG则是从框架设计层面就把这些场景作为一等公民来支持。这也是为什么在Selenium、Appium这类自动化测试的教程和面试题里TestNG的出镜率一直居高不下。1.2 TestNG的技术血缘与设计哲学TestNG由Cedric Beust在2004年创建他的动机很直接——想做一个比JUnit更强大、更灵活的测试框架。如果你读过TestNG的官方文档会发现它对“什么是测试”的理解比JUnit广得多。JUnit的根基是“单元测试”强调隔离、快速、确定性TestNG的根基是“测试全生命周期”从单元到集成再到端到端都试图用一种统一的模型来覆盖。这个设计哲学体现在几个具体点上用XML文件驱动测试的组装和执行而不是全依赖代码里的注解。这意味着测试的执行计划可以脱离代码单独维护QA同学不改代码也能调整测试范围。提供IAnnotationTransformer这类接口允许在运行时动态修改注解的行为。这个能力在JUnit里很难做到但在做适配层和框架封装时非常有用。内置了线程池和并发执行模型同一份测试代码不需要额外引入并发框架就能配置并行策略。我自己理解TestNG整套设计的一个关键词叫“可编排”。JUnit把测试组织方式限定在“类-方法”的二维结构里TestNG往上抽象了一层“测试套件-Suite→测试-Test→类-Class→方法-Method”的四级结构并且每一级都可以配置执行策略、监听器、参数。这种编排能力是它能在大型自动化项目中立住脚的根本原因。1.3 TestNG与JUnit 4的关键能力对比拿一张表直观对比一下两者在核心能力上的差异方便你判断自己项目里该用哪个能力维度JUnit 4TestNG基本注解Test, Before, AfterTest, BeforeMethod, AfterMethod, BeforeClass, AfterClass测试分组无原生支持需自定义Runner原生支持groups属性可配置组合逻辑参数化RunWith(Parameterized.class)写法较重DataProvider方法直接返回Object[][]或Iterator依赖测试不支持Test(dependsOnMethods) / Test(dependsOnGroups)并行执行JUnit 4.7 有实验性支持原生支持parallel属性稳定执行计划管理靠IDE插件和Gradle/Maven配置支持testng.xml可按套件定义执行范围测试结果监听Rule 或 RunnerITestListener接口覆盖粒度更细失败重跑需要第三方RuleIRetryAnalyzer接口机制清晰看完表格你应该有感觉了JUnit 4像一套约定俗成的“标准件”TestNG更像一个能自定义装配的“平台”。当然JUnit 5已经引入了大量新特性很多差距被追回来了但TestNG生态经过十几年的沉淀在自动化测试领域的成熟方案和踩坑记录都非常丰富这也是它至今仍有很强生命力的原因。2. TestNG的四级执行模型从testng.xml开始理解“可编排”的底气TestNG最容易被新手忽略却最值得花时间研究的就是它的XML驱动机制。很多人习惯了在IDE里右键直接跑测试方法完全绕过了testng.xml这其实相当于放弃了TestNG最核心的编排能力。2.1 XML驱动模式的底层逻辑TestNG解析testng.xml后会构建一棵XmlSuite → XmlTest → XmlClass → 方法的执行树然后交给SuiteRunner类逐级执行。XML文件在这里扮演的角色不是“配置文件”这么简单它定义的是整个测试执行的“剧本”。一个标准testng.xml长这样!DOCTYPE suite SYSTEM https://testng.org/testng-1.0.dtd suite name全部回归测试 verbose2 parallelmethods thread-count4 test name订单模块 preserve-ordertrue parameter nameenv valuestaging / groups run include namesmoke / exclude namebroken / /run /groups classes class namecom.example.tests.OrderTest / class namecom.example.tests.PaymentTest / /classes /test /suite注意看suite标签上的parallelmethods和thread-count4。这两行代码的意思是Suite内的方法级测试可以并行执行最多4个线程。在JUnit 4里要实现类似效果你得引入额外的Runner或者依赖Gradle的并行配置但在TestNG里这就是一个属性的事。2.2 四种执行组件的作用域与组合方式我想多说几句这四个层级各自的定位因为理解了作用域你才能正确地组织测试代码Suite顶层容器通常对应一次完整的回归测试、或者某个大版本的功能验证。一个Suite里可以包含多个Test。Test这里的Test不是指一个用例方法而是指一类测试场景的组合比如“订单流程”“会员中心”。不同Test之间可以设置不同的运行参数和监听器。ClassJava测试类。一个Test下面可以挂多个Class。注意同一个Class可以被不同Test引用只是执行时参数可以不同。Method最小的执行单元就是带Test注解的方法。套件之间彼此隔离又可以通过dependsOnGroups这样的机制建立“软关联”这比硬编码执行顺序优雅得多。2.3 从一次真实用例运行看执行链路带大家走一遍实际执行链路你就能串起来理解。假设我们跑上面那份XMLTestNG的处理流程是这样的解析XML创建XmlSuite对象读取全局参数。遍历XmlTest把订单模块下的Class加载进JVM。分析每个Class内部的方法识别Test、BeforeMethod、DataProvider等注解生成可执行方法列表。根据groups配置做一次方法过滤把包含smoke分组的方法选出来排除broken分组。启动线程池在4个线程中开始执行方法。每个方法执行前先执行所属类的BeforeClass再执行每个方法都需要的BeforeMethod。方法执行结束后触发监听器接口比如记录测试结果的ITestListener最后统一生成报告。这个过程里最容易被忽略的是第四步和第五步。分组过滤决定了“跑哪些”线程池决定了“怎么并发”。很多团队并行跑了但没真正生效多半是没搞清楚这两个机制的配合。我见过一个项目在testng.xml里配了parallelmethods但测试类里所有用例都共享同一个静态WebDriver实例结果一并发就各种串数据。这不是TestNG的问题是并行策略和资源隔离没设计好。后面我会专门讲这个话题。3. 注解体系的工程化姿势生命周期、分组、参数化与依赖TestNG的注解体系比JUnit丰富不少但“注解多”不等于“用得多就好”。在真实项目里我见过太多人把BeforeMethod当成万能初始化用结果每次执行用例之前都重新启动浏览器、清空数据库跑一个用例要两分钟。注解用错了位置比不用更糟糕。3.1 生命周期注解的使用边界与规范先看TestNG提供的生命周期注解表注解执行时机典型使用场景BeforeSuite整个Suite执行前生成测试数据目录、初始化全局配置AfterSuite整个Suite执行后清理临时文件、发送汇总报告BeforeTest当前 标签内所有类执行前初始化这个测试场景特有的环境AfterTest当前 标签内所有类执行后回收场景级资源BeforeClass当前测试类实例创建后、第一个方法执行前创建类的共享WebDriver实例注意线程问题AfterClass当前测试类所有方法执行后关闭浏览器、清理类级数据BeforeMethod每个Test方法执行前登录操作、打开页面、准备前置数据AfterMethod每个Test方法执行后用例结果记录、失败截图、数据清理BeforeGroups指定分组执行前对某分组做特殊初始化AfterGroups指定分组执行后分组级清理这里面工程化的关键是“资源初始化粒度”。我个人的经验法则是能提升到Class级或者Suite级初始化的绝不放在Method级。比如数据库连接、测试账号池、浏览器实例在非并行模式下这些在Class级初始化一次就够了。而每个Method前只做和当前用例相关的动作比如“打开指定URL”“设置Cookie”。拿UI自动化举例一个常见的反模式是BeforeMethod public void setUp() { driver new ChromeDriver(); driver.get(https://example.com); login(user, password); }每条用例都重新启动浏览器、重新登录用例一多跑起来极其浪费时间。正确做法是如果用例之间不互相影响页面状态就把浏览器实例放到BeforeClass里BeforeMethod只负责导航到目标URL。当然并行执行的场景要另说这个在后文展开。3.2 DataProvider参数化测试数据从哪来、怎么传参数化是自动化测试里的高频需求。TestNG的Parameters适合传环境信息这类固定参数而 DataProvider适合传多组测试数据。一个经典的登录测试写法DataProvider(name loginData) public Object[][] provideLoginData() { return new Object[][] { {user1, pass1, true}, {user2, wrongPass, false}, {, pass, false} }; } Test(dataProvider loginData) public void testLogin(String username, String password, boolean expectedResult) { boolean actual loginService.login(username, password); Assert.assertEquals(actual, expectedResult); }表面上看起来很简单但工程化之后有几个细节值得注意第一Object[][]只是最基础的形式。当数据量特别大时一次性把所有数据全加载到内存里是浪费的。用IteratorObject[]可以做到懒加载按需迭代才取数据。第二DataProvider本身支持参数可以从XML里接收环境信息然后决定从哪个数据源读取数据。比如我可以让一个DataProvider根据当前环境从MySQL、Excel、YAML里分别加载数据。第三失败信息的可读性。当数据驱动用例失败时默认报告只会告诉你是第几组数据挂了但哪一组数据的具体值是什么经常看不到。我一般会在测试方法里把当前参数打印到日志或者自定义断言信息否则排查成本相当高。3.3 依赖测试与分组处理用例之间的顺序关系依赖测试是TestNG比JUnit强很多的点。说白了就是允许你在注解里声明“我这个用例依赖另一个用例”如果被依赖的用例失败了依赖它的用例会被直接跳过并标记为skipped而不是继续跑完再给你一堆无效的失败。写法也很简单Test public void testLogin() { // ... } Test(dependsOnMethods testLogin) public void testCreateOrder() { // ... } Test(dependsOnMethods testCreateOrder) public void testPayOrder() { // ... }看起来很方便但我得泼一盆冷水依赖测试在端到端流程类用例里好用但不建议在单元测试或者功能独立的用例里滥用。因为一旦用例之间形成长链依赖前面任意一个挂了后面全部被跳过测试报告会充满“黄色”排查起来很费劲。我见过更稳的做法是用分组来管理“类型”用依赖来管理“流程”。按类型分组Test(groups {smoke, user})表示这个是冒烟测试里的用户模块用例。按流程依赖像下单→支付→出库这种确实是业务强流程用dependsOnMethods是合理的。另外TestNG还支持dependsOnGroups粒度更粗。比如我可以定义Test(groups {initData})是初始化数据的用例其他所有用例都依赖这个组这样至少保证了执行顺序的稳定性。这个思路在做大型回归时很实用。4. 接入真实自动化项目Selenium、Appium、接口测试的整合实践TestNG从来不是孤立存在的脱离了Selenium、Appium、HTTP客户端这些执行工具它只是个组织用例的空壳。反过来如果只有这些工具没有TestNG整合用例管理依然是一团乱麻。两者结合才是自动化框架的常态。4.1 整合Selenium时TestNG要解决的三个问题以Web自动化为例TestNG接入Selenium后第一个要解决的是“Driver实例的创建与传递”。我见过不少新手直接在一个静态变量里存WebDriver用例并发一开浏览器串台所有用例全挂。正解是借助TestNG的Parameters和线程安全机制每线程独立Driver实例。代码结构一般是这样public class BaseTest { protected WebDriver driver; BeforeClass Parameters(browser) public void setup(String browser) { driver DriverFactory.createInstance(browser); driver.manage().window().maximize(); } AfterClass public void teardown() { if (driver ! null) { driver.quit(); } } }第二个问题是失败用例的截图。UI自动化最怕元素定位失败一张截图能省掉大量沟通成本。我会在自定义监听器里监听onTestFailure事件截图后附到测试报告里。第三个问题是等待策略。Selenium的隐式等待和显式等待经常混用出问题我会在BaseTest里统一封装一个waitForElementVisible的方法并用TestNG的软断言配合轮询避免用例一遇到元素还没加载就立刻失败。4.2 接口自动化中TestNG如何配合HTTP客户端接口自动化里TestNG的价值主要体现在参数组织和依赖处理上。比如用DataProvider批量传接口请求参数用dependsOnMethods保证“创建订单→查询订单→取消订单”的顺序用ITestListener统一记录接口响应时间。一个非常实用的组合是DataProviderRestAssuredTestNG断言。DataProvider(name createOrderData) public Object[][] orderData() { return new Object[][] { {userA, item001, 2, 200}, {userB, item002, -1, 400}, }; } Test(dataProvider createOrderData, groups {interface, order}) public void testCreateOrder(String user, String itemId, int quantity, int expectedCode) { Response response RestAssured.given() .body(orderJson(user, itemId, quantity)) .post(/api/orders); Assert.assertEquals(response.getStatusCode(), expectedCode); Assert.assertNotNull(response.jsonPath().getString(orderId)); }这套组合的好处是数据驱动、断言清晰、失败定位快。接口自动化里HttpClient和RestAssured的选择看团队习惯但骨架和TestNG的配合逻辑是通用的。4.3 并行测试与资源隔离一个现实中很容易翻车的主题不少人一提到并行就只想到在testng.xml里加parallelmethods其实这只是万里长征第一步。真正难的是测试资源怎么隔离。以接口测试为例如果你用的测试环境是共享的两个用例同时操作同一个账号、同一个订单数据必然互相污染。这时候要么做数据隔离每个线程用唯一用户名要么做数据申请从池子里取账号要么在用例设计阶段就避免共享可变数据。以UI测试为例并行跑浏览器默认就是隔离的因为每个WebDriver实例对应一个独立浏览器进程。但问题出在测试数据上比如多个并发用例同时注册同一个手机号后注册的必然失败。我当时的一个经验是把手机号生成规则做成“时间戳随机数”从源头消掉冲突。所以并行前先回答三个问题并发用例之间是否共享了测试数据每个线程是否有独立的资源实例数据库、浏览器、请求客户端失败用例后资源能否被彻底清理而不影响其他线程这三个问题没有靠谱答案之前不建议盲目开并行。5. 结果反馈与CI落地监听器、报告、失败重跑、多环境切换测试跑完了反馈链路才算真正开始。TestNG在这块提供了很完整的机制但我发现很多团队只用了默认的emailable-report太浪费了。5.1 TestNG的报告体系与自定义改造TestNG默认会生成index.html和emailable-report.html信息包括每个方法的耗时、状态、异常堆栈。简单场景够用但大型项目里你需要的是“能一眼看出哪个模块失败率最高”的聚合报告。我通常会在项目里基于ITestListener接口自定义一套报告。ITestListener提供onTestStart、onTestSuccess、onTestFailure、onTestSkipped等回调我可以在里面收集用例名、所属类、耗时、异常信息然后输出成JSON再交给后续脚本渲染成HTML或推送到消息平台。一个最基础的自定义监听器实现public class TestResultListener implements ITestListener { Override public void onTestFailure(ITestResult result) { // 记录失败用例的方法名、参数、异常堆栈到日志文件 System.out.println(FAILED: result.getName()); System.out.println(Exception: result.getThrowable()); // 如果是UI测试这里还能调用截图工具把当前页面截图存下来 } Override public void onTestSuccess(ITestResult result) { System.out.println(PASSED: result.getName()); } }别忘了在testng.xml里注册监听器listeners listener class-namecom.example.framework.TestResultListener / /listeners5.2 失败重跑机制用IRetryAnalyzer解决“偶发失败”难题接口自动化或者UI自动化里总有那么几条用例“时而通过时而失败”大多是网络抖动、元素加载超时这类环境问题。每条失败用例都去人工看一遍没必要直接改断言降低标准更是饮鸩止渴。这时候用IRetryAnalyzer去做重试是最合适的。实现起来也不复杂public class RetryAnalyzer implements IRetryAnalyzer { private int retryCount 0; private static final int MAX_RETRY_COUNT 2; Override public boolean retry(ITestResult result) { if (retryCount MAX_RETRY_COUNT) { retryCount; return true; } return false; } }使用时在Test注解上挂retryAnalyzer RetryAnalyzer.class。但重试也要谨慎。接口写操作类的用例不适合无脑重试比如“创建订单”接口第一次调用其实成功了只是响应超时这时重试就等于创建了两笔订单。对于这类幂等性没法保证的接口我更建议用测试数据里的唯一标识做幂等处理或者只在只读查询类用例上开重试。5.3 多环境与多浏览器配置testng.xml的工程化封装TestNG的Parameters配合XML可以在不同环境之间切换。我常用的做法是维护多份XML配置文件比如testng-staging.xml、testng-prod.xml、testng-chrome.xml、testng-firefox.xml需要跑哪个环境就指定对应的XML。也可以在XML里定义suite级别的参数suite nameAPI测试 parameter namebaseUrl valuehttps://staging-api.example.com / parameter nametimeout value5000 / ... /suiteJava侧用Parameters接收BeforeSuite Parameters({baseUrl, timeout}) public void initSuite(String baseUrl, int timeout) { // 设置全局配置 Config.baseUrl baseUrl; Config.timeout timeout; }再配合Maven的Profile或者Jenkins的参数化构建就可以做到构建时动态选环境了。这一套组合拳打下来测试框架才算真正能交到团队每个人手里用而不是只有写框架的人自己会跑。6. 面试与团队推广TestNG相关的高频考点和落地建议最后聊聊面试题和团队落地这两个偏“软”的话题。毕竟TestNG作为Java测试栈里的常青树面试几乎必问团队想推进技术改造的时候也绕不开。6.1 面试官喜欢问的TestNG问题我总结几个面试中最高频的问题供大家查漏补缺TestNG和JUnit的区别是什么这个问题考察的不是背对比表而是看你怎么表达。我会从“JUnit定位单元测试TestNG定位全场景”“TestNG提供依赖测试和分组”“XML驱动便于维护执行计划”这几个核心差异入手再举例说明自己项目里因为哪个痛点才选型TestNG。BeforeMethod和BeforeClass的使用区别答清楚执行时机只是基础加分项是说出资源初始化粒度和性能影响。如何实现失败用例重跑答IRetryAnalyzer是标准答案能顺手讲出重试对非幂等接口的风险基本就能让面试官记住你。如何设计接口测试的数据驱动说DataProvider是入门加分项是结合项目讲清楚数据源Excel、YAML、数据库和懒加载实现方式。TestNG的监听器有哪些至少能说出ITestListener、IInvokedMethodListener、IHookable、IAnnotationTransformer中的两到三个并说清各自用途。6.2 把TestNG引入团队时的落地顺序如果你是团队的测试开发或者QA负责人想把TestNG这套体系引入现有项目我的建议是从小处切入不要一上来就推翻现有框架。第一步先拿一个自动化程度不高的小模块做试点搭建BaseTesttestng.xml自定义监听器的最小骨架跑通一条链路。第二步固化项目模板。把BaseTest、DriverFactory如果做UI自动化、DataProvider的加载逻辑、监听器配置整理成公司内部脚手架新项目直接复用。第三步把执行计划纳入CI流水线。在Jenkins或者GitLab CI里配置构建参数让开发提交代码后自动触发冒烟测试测试结果回传到工作群。第四步逐步完善失败分类机制。把网络超时、元素找不到、断言失败分别归类建立失败信息和业务模块的映射关系。这些数据积累起来后团队就能看到真实的测试质量趋势而不仅仅是“今天挂了几个”。我在多个项目里按这个顺序落地效果都还不错踩的坑最少、团队接受度也最高。6.3 关于TestNG与JUnit 5的选型争论说了这么多TestNG的好话也要客观说一句JUnit 5已经追上了很多差距比如Tag标签、ParameterizedTest、TestFactory这些特性都在向TestNG的能力靠拢。新项目如果团队对JUnit更熟用JUnit 5也不会有太大问题。那TestNG还值得学吗我的判断是值得而且很值得。理由有三点第一存量项目庞大。现在线上大量Java自动化测试项目尤其Selenium、Appium生态里TestNG的代码基数非常大维护这些项目必然需要懂TestNG的人。第二TestNG的XML驱动模型在企业级场景里仍然高效。JUnit 5虽然也有Tag但在复杂套件编排、多环境分组执行上TestNG的XML方案依然更成熟。第三理解TestNG的设计思路能帮你更好地理解测试框架要解决的通用工程问题。这些认知迁移到JUnit 5、pytest、Playwright等其他框架上都是通用的。所以我的建议是如果是从零开始选型可以结合团队技能栈二选一如果要面试测试开发岗或者要接手维护老项目TestNG是绕不开的基础技能。框架只是手段真正值钱的是你对测试组织、执行策略、结果分析这套工程方法的理解而TestNG正好是帮助你建立这套理解的一个极好载体。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

Presenton Mac App Store 构建实战:MAS 打包的证书、Profile 与脚本完整避坑指南 2026/10/2 2:10:47

Presenton Mac App Store 构建实战:MAS 打包的证书、Profile 与脚本完整避坑指南

Presenton Mac App Store 构建实战:MAS 打包的证书、Profile 与脚本完整避坑指南 【免费下载链接】presenton Open-Source AI Presentation Generator and API (Gamma, Canva, Beautiful AI, Decktopus, Presentations AI Alternative) 项目地址: https://gitcode…

阅读更多 →
Extreme Networks 远程职位档案解析:一个 fully-remote 网络技术公司的社区目录实践 2026/10/2 2:10:40

Extreme Networks 远程职位档案解析:一个 fully-remote 网络技术公司的社区目录实践

数据集 【免费下载链接】remote-jobs Source for remoteintech.company — a community-maintained directory of remote-friendly tech companies 项目地址: https://gitcode.com/GitHub_Trending/re/remote-jobs 点击查看 免费下载 Extreme Networks 是 remotein…

阅读更多 →
5万骑手每5秒上报位置?高并发位置上报系统架构设计实战 2026/10/2 2:10:34

5万骑手每5秒上报位置?高并发位置上报系统架构设计实战

1. 先算一笔账:5万骑手每5秒上报一次,到底会产生多大的压力?先说结论:不会“写死”,但如果是裸奔的常规架构,大概率会“写瘫”。关键在于,很多人一听到“5万”“每5秒”就下意识觉得量很大&…

阅读更多 →
system-design-101 密码安全存储全指南:从加盐(Salt)到哈希校验的完整实战 2026/10/2 2:10:34

system-design-101 密码安全存储全指南:从加盐(Salt)到哈希校验的完整实战

后端文档教程 【免费下载链接】system-design-101 Explain complex systems using visuals and simple terms. Help you prepare for system design interviews. 项目地址: https://gitcode.com/GitHub_Trending/sy/system-design-101 点击查看 免费下载 密码是大多…

阅读更多 →
Victor Mono 字体在 Nerd Fonts 仓库中的补丁变体指南:NF / NFM / NFP 选择、连字保留与自行 Patch 实战 2026/10/2 2:10:34

Victor Mono 字体在 Nerd Fonts 仓库中的补丁变体指南:NF / NFM / NFP 选择、连字保留与自行 Patch 实战

开发工具CLI 【免费下载链接】nerd-fonts Iconic font aggregator, collection, & patcher. 3,600 icons, 50 patched fonts: Hack, Source Code Pro, more. Glyph collections: Font Awesome, Material Design Icons, Octicons, & more 项目地址: https://…

阅读更多 →
Marketing Skills 仓库中的 Beehiiv 集成指南:用 REST API v2 与 CLI 构建 Newsletter 自动化工作流 2026/10/2 2:10:34

Marketing Skills 仓库中的 Beehiiv 集成指南:用 REST API v2 与 CLI 构建 Newsletter 自动化工作流

AI 技能人工智能 【免费下载链接】marketingskills Marketing skills for Claude Code and AI agents. CRO, copywriting, SEO, analytics, and growth engineering. 项目地址: https://gitcode.com/GitHub_Trending/mar/marketingskills 点击查看 免费下载 本文面…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉