Playwright 简明入门教程:录制自动化测试用例,结合 Docker 使用

news/2024/4/16 17:13:04/文章来源:https://blog.csdn.net/soulteary/article/details/128089864

本篇文章聊聊如何使用 Playwright 进行测试用例的录制生成,以及如何在Docker 容器运行测试用例,或许是网上最简单的入门教程。

写在前面

Playwright 是微软出品的 Web 自动化测试工具和框架,和 Google Puppeteer 有着千丝万缕的关系。前一阵答应了小伙伴,要做一些自动化测试相关的分享。本篇作为第一篇,聊聊怎么简单的玩 Playwright 。

在 playwright 或者 puppeteer 的开源项目中,不论是文档还是示例,有不少内容倾向于编写代码的方式(Coding)来进行自动化测试相关的动作。

然而,需要和页面打交道的前端交互测试,有一个麻烦的事儿,就是我们需要不停在浏览器和代码编辑器中进行切换,定位要交互的元素,把要操作的元素的路径、位置拿到,思考要怎么模拟用户的操作,触发页面的事件或者程序中内置钩子方法,然后切换到代码编辑器里,再编写胶水逻辑,往复循环数次,完成基础的测试程序。接下来,还要和写被测试代码一样,验证程序运行是否正确等等,整个操作流程其实还是挺麻烦的

但这就完事了嘛?并没有,面向用户的界面的迭代变化频率是非常高的,基于界面元素构建的测试程序自然也要跟着变,那么我们面临的就是不停的折腾自己,有没有省事儿一点的方法呢

好在我们还有另外一种选择,通过“录制为主,编写为辅”的方式来完成测试程序,而不是用上面的方式循环的折腾自己,毕竟偷懒是工程师的美德嘛

搞定 Playwright 本地录制环境

我们可以使用 Playwright Python 来完成简单的测试用例录制,关于 Python 的安装, 就不多赘述了,在 macOS 和 Ubuntu 等操作系统中是内置的 Runtime(也可以使用 brew 或者 apt 来安装或者进行升级),在 Windows 中,我们可以通过非常多的方式来完成安装。

如果你希望更快的完成 Playwright 的 Python PyPI 软件包的下载安装,可以执行下面的命令,替换软件源为清华源:

pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

下载基础软件工具

接着,我们执行 pip3 install playwright 就能够完成 playwright Python 版基础程序的安装了啦:

...
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting playwrightDownloading https://pypi.tuna.tsinghua.edu.cn/packages/97/35/28f880594a6e0b89475e21073b83ab374e522ab1fbf86849585ecc4a4e19/playwright-1.28.0-py3-none-macosx_11_0_universal2.whl (30.6 MB)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 30.6/30.6 MB 255.8 kB/s eta 0:00:00
...
...
Installing collected packages: typing-extensions, greenlet, pyee, playwright
...
...
Successfully installed greenlet-2.0.1 playwright-1.28.0 pyee-9.0.4 typing-extensions-4.4.0

完成基础软件的安装之后,我们执行 playwright 能够看到程序 CLI 的基本用法。

Usage: playwright [options] [command]Options:-V, --version                          output the version number-h, --help                             display help for commandCommands:open [options] [url]                   open page in browser specified via -b, --browsercodegen [options] [url]                open page and generate code for user actionsinstall [options] [browser...]         ensure browsers necessary for this version of Playwright are installedinstall-deps [options] [browser...]    install dependencies necessary to run browsers (will ask for sudo permissions)cr [options] [url]                     open page in Chromiumff [options] [url]                     open page in Firefoxwk [options] [url]                     open page in WebKitscreenshot [options] <url> <filename>  capture a page screenshotpdf [options] <url> <filename>         save page as pdfshow-trace [options] [trace...]        show trace viewerhelp [command]                         display help for command

到现在为止,我们距离完成本地环境的安装还差一步,因为现在我们只有软件基础框架,并没有要进行测试的浏览器环境(Chrome、Firefox 等等),所以我们还要进行浏览器环境下载。

下载需要的浏览器环境

浏览器环境的下载需要使用 playwright install 命令,目前支持通过命令下载下面的浏览器:chromium、chrome、chrome-beta、msedge、msedge-beta、msedge-dev、firefox、webkit。

当然,不同版本的 playwright 可能支持的浏览器列表是不同的,我们可以通过 playwright install --help 来查看下载的 playwright 到底支持什么浏览器。

playwright install --help
Usage: playwright install [options] [browser...]ensure browsers necessary for this version of Playwright are installedOptions:--with-deps  install system dependencies for browsers--dry-run    do not execute installation, only print information--force      force reinstall of stable browser channels-h, --help   display help for commandExamples:- $ installInstall default browsers.- $ install chrome firefoxInstall custom browsers, supports chromium, chrome, chrome-beta, msedge, msedge-beta, msedge-dev, firefox, webkit.

比如,我们只需要测试 Chrome 环境下的程序表现,那么可以执行下面的命令:

playwright install chrome

完成第一个测试用例

当我们完成 Playwright 的环境安装和配置之后,我们就可以进行第一个测试用例的录制了。

“搜索”需求是一个有趣的例子,可以覆盖用户在页面中常见的交互动作,包含:打开页面、选择可交互的页面替换元素(Input)、跳转新页面等等。

前一阵“宝可梦”发布了新版本,作为一个还没开始玩的用户,难免对这款游戏心心念念。那么测试用例,就选择通过录制用户在搜索引擎中搜索“宝可梦”新游戏百科词条,在新窗口中打开词条中游戏的第一条宣传视频,来解解馋吧。

自动化录制完成测试用例初版

接下来,我们先来创建一个目录,用于保存接下来生成的测试程序文件:

mkdir -p playwright
cd playwright

接着,执行下面的命令,程序将自动打开两个窗口,包含一个浏览器窗口(起始页面是 https://cn.bing.com,当我们完成录制,结果将保存在 pokemon.js 文件中):

playwright codegen -o pokemon.js --target javascript https://cn.bing.com

Playwright 自动打开交互窗口

我们在搜索框中输入“宝可梦朱紫”,然后和平时一样敲击回车键(也可以戳搜索按钮),页面会来到搜索结果页。同时,Playwright Inspector 窗口中,会生成模拟我们交互行为的代码。

Playwright 录制的搜索过程

我们点击第一条搜索结果:“百科内容”,将打开一个新的窗口。

Playwright 录制新窗口内容

接着,我们选择页面中的第一个视频元素,将出现一个视频播放器。如果浏览器的解码器正常的话,我们将能够顺利得到播放的视频画面。这里因为默认启动的浏览器环境中,缺少一些解码器,所以无法进行播放。后续的文章中我将介绍如何解决这个问题,因为不是本篇文章的重点,所以就不展开啦。

Playwright 打开的播放器窗口

目前为止,我们已经完成了本小节设置的测试目标,所以可以关闭窗口,完成录制。当我们关闭测试使用的浏览器窗口之后,录制代码将自动保存在我们的文件夹中。

使用 cat pokemon.js 命令查看代码,可以看到类似下面的内容:

const { chromium } = require('playwright');(async () => {const browser = await chromium.launch({headless: false});const context = await browser.newContext();const page = await context.newPage();await page.goto('https://cn.bing.com/');await page.getByRole('searchbox', { name: '输入搜索词' }).click();await page.getByRole('searchbox', { name: '输入搜索词' }).fill('宝可梦朱紫');await page.getByRole('searchbox', { name: '输入搜索词' }).press('Enter');const [page1] = await Promise.all([page.waitForEvent('popup'),page.getByRole('link', { name: '宝可梦朱·紫_百度百科' }).click()]);await page1.locator('#J-video-list div').filter({ hasText: '一分钟了解游戏宝可梦朱·紫 00:55' }).nth(2).click();await page1.locator('svg').filter({ hasText: '.st0{fill:none;}' }).click();await page1.close();await page.close();// ---------------------await context.close();await browser.close();
})();

使用 Node.js 来验证测试用例是否可用

通过 Playwright 生成的代码很多时候并不是完全“work”的,我们可以在完成录制之后,通过 Node.js 来进行测试用例的验证。(你也可以切换为程序支持的、你喜欢的其他语言)

通过 Node 执行我们生成的代码文件:

node pokemon.js

运行我们在文字上面小节中生成的代码,将会自动打开一个新的浏览器窗口,然后在百科页面不停的上下滚动,好像在寻找着什么东西。不久之后,我们将得到一个执行超时报错:

node:internal/process/promises:246triggerUncaughtException(err, true /* fromPromise */);^locator.click: Timeout 30000ms exceeded.
=========================== logs ===========================
waiting for locator('#J-video-list div').filter({ hasText: '一分钟了解游戏宝可梦朱·紫 00:55' }).nth(2)locator resolved to visible <div class="second-video-item-mask"></div>
attempting click actionwaiting for element to be visible, enabled and stableelement is visible, enabled and stablescrolling into view if neededdone scrolling<div class="second-video-item-player J-second-player-></div> intercepts pointer events
retrying click action, attempt #1waiting for element to be visible, enabled and stableelement is visible, enabled and stablescrolling into view if neededdone scrolling
...
...
============================================================at /Users/soulteary/Lab/playwright/pokemon.js:17:149 {name: 'TimeoutError'
}

出现这个错误的原因,是因为我们在录制的时候,可能选择到了因为一些特殊条件才会出现的元素路径,或者浏览器中的 JavaScript 随机生成的 HTML Elements 标识(IDClass 等等)。

这个时候,需要我们打开有问题的页面,手动调整需要交互的元素的“定位方式”或者交互方式。比如,这里出现问题的是这一行代码:

await page1.locator('#J-video-list div').filter({ hasText: '一分钟了解游戏宝可梦朱·紫 00:55' }).nth(2).click();

它告诉 Playwright 在新打开的页面 page1 中先找到 #J-video-list 下所有的 div 然后找到包含“一分钟了解游戏宝可梦朱·紫 00:55”文本内容的元素,然后选择这个元素中的第二个(nth(2))子元素,点击它,唤起视频播放器。

这里先不必纠结程序为什么会生成这样一个错误的路由规则,来看看如何简单的解决这个问题吧。后面有机会可以分享下几年前我做自动化测试时,关于页面唯一路径生成的算法实践。

我们可以手动打开一个相同的页面,然后打开页面调试工具,选择一个我们认为合适的有辨识度的元素标识,比如:.J-second-video-item-player-container

为 Playwright 选择合适的元素标识

在完成选择之后,我们可以通过在浏览器控制台通过执行下面的代码,来验证查找定位的元素是否和我们预期中的一样(相同且唯一):

Array.from(document.querySelectorAll('.J-second-video-item-player-container')).filter((item)=>item.innerText.includes('一分钟了解游戏宝可梦朱·紫'))

这里有一个小技巧,我们在验证任意子元素中“包含文本内容”的时候,可以把空格之后的内容删除掉,不影响最终结果。

验证元素标识完毕之后,我们来调整生成的代码:

const { chromium } = require('playwright');(async () => {const browser = await chromium.launch({headless: false});const context = await browser.newContext();const page = await context.newPage();await page.goto('https://cn.bing.com/');await page.getByRole('searchbox', { name: '输入搜索词' }).click();await page.getByRole('searchbox', { name: '输入搜索词' }).fill('宝可梦朱紫');await page.getByRole('searchbox', { name: '输入搜索词' }).press('Enter');const [page1] = await Promise.all([page.waitForEvent('popup'),page.getByRole('link', { name: '宝可梦朱·紫_百度百科' }).click()]);await page1.locator('.J-second-video-item-player-container').filter({ hasText: '一分钟了解游戏宝可梦朱·紫 00:55' }).click();await page1.locator('svg').filter({ hasText: '.st0{fill:none;}' }).click();await page1.close();await page.close();// ---------------------await context.close();await browser.close();
})();

接着,我们再次执行 node pokemon.js,这次浏览器将符合我们的预期执行:打开搜索引擎,输入要搜索的内容,点击搜索结果的百科条目,然后在新窗口中打开视频播放页面。

当程序执行完毕,也不会再有任何报错信息,我们的第一个“自动化测试”也就搞定啦。

将测试用例迁移到 Docker 容器中

在上面的文章内容中,我们完成了本地的测试和交互验证。如果我们将需要测试的应用的交互功能都进行录制,并且在代码提交的时候、版本发布的时候调用 Playwright 进行测试用例的执行,只把运行结果发送给我们,随着测试测试次数的积累,那么将能节省非常多不必要的“人力成本”。

毕竟偷懒是工程师的美德嘛。

不过总是拿我们自己的设备来进行测试,其实并不现实:除非你舍得自己的设备 7x24 小时开机跑执行程序,并且能够确保这台供电和网络非常稳定,以及你的电脑真的可以只做这一件事。所以,我们一般会考虑使用云服务器、结合 CI 来完成这些工作。

为了稳定、高效地进行测试用例的回归验证,我们可以选择使用稳定的 Docker 容器来作为测试用例的执行环境,这样一台服务器上实际可以同时运行非常多的测试用例,并且测试用例之间彼此互相隔离,不会影响和干预执行过程和结果。

启动一个容器“浏览器”服务

想要在容器中稳定的运行 Chrome ,将 Chrome 作为服务提供给其他的应用使用,推荐使用 Browserless 这个开源项目。

Browserless

如果你在本地或者云服务器安装了 Docker,那么可以通过下面的命令,快速启动一个包含了 Chrome 的容器实例,用于测试验证测试程序是否正常:

docker run --rm -it -p 3000:3000 -e "MAX_CONCURRENT_SESSIONS=10" browserless/chrome:1-puppeteer-19.2.2

如果你想作为服务运行,可以去掉 --rm -it,替换为 -d 参数,或者使用 compose 编排文件,搭配更多参数来执行。Browserless 支持的完整的配置项目可以在 Browserless 文档 中找到,在命令执行完毕,我们将得到类似下面的日志。

  browserless:server {browserless:server   CONNECTION_TIMEOUT: 60000,browserless:server   MAX_CONCURRENT_SESSIONS: 10,browserless:server   QUEUE_LENGTH: 10,browserless:server   SINGLE_RUN: false,browserless:server   CHROME_REFRESH_TIME: 1800000,
...

调整测试用例程序代码

搞定了测试环境之后,我们对之前调整过的自动生成的测试做一个“副本”:

cp pokemon.js pokemon-in-docker.js

然后找到代码中的启动浏览器的代码:

const browser = await chromium.launch({headless: false
});

将其替换为调用 CDP 协议启动 Docker 中的浏览器( localhost 这个地址需要调整为你启动服务的可访问地址):

const browser = await chromium.connectOverCDP("ws://localhost:3000");

保存代码,执行 node pokemon-in-docker.js 稍等片刻,程序就顺利执行完毕了,因为实际的执行过程在远端(容器中),所以这次不会弹出任何浏览器窗口。

在 Docker 容器的日志中,我们将看到类似下面的输出:

  browserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: /: Inbound WebSocket request. +3hbrowserless:hardware Checking overload status: CPU 1% Memory 12% +3hbrowserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Adding new job to queue. +3msbrowserless:server Starting new job +4mbrowserless:system Generating fresh chrome browser +3hbrowserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Getting browser. +0msbrowserless:chrome-helper Launching Chrome with args: {browserless:chrome-helper   "args": [
...
...browserless:chrome-helper } +3hbrowserless:chrome-helper Chrome PID: 482 +124msbrowserless:chrome-helper Finding prior pages +1msbrowserless:chrome-helper Found 1 pages +16msbrowserless:chrome-helper Setting up page Unknown +0msbrowserless:chrome-helper Injecting download dir "/usr/src/app/workspace" +0msbrowserless:system Chrome launched 142ms +142msbrowserless:system Got chrome instance +0msbrowserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Starting session. +142msbrowserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Proxying request to /devtools/browser route: ws://127.0.0.1:39839/devtools/browser/5453abb9-b24e-4302-9212-e227749c5d79. +0msbrowserless:chrome-helper Setting up file:// protocol request rejection +2msbrowserless:chrome-helper Setting up page Unknown +246msbrowserless:chrome-helper Injecting download dir "/usr/src/app/workspace" +0msbrowserless:chrome-helper Setting up file:// protocol request rejection +1msbrowserless:chrome-helper Setting up page Unknown +2sbrowserless:chrome-helper Injecting download dir "/usr/src/app/workspace" +0msbrowserless:chrome-helper Setting up file:// protocol request rejection +2msbrowserless:server W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Recording successful stat and cleaning up. +6sbrowserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Cleaning up job +6sbrowserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Browser not needed, closing +0msbrowserless:chrome-helper Shutting down browser with close command +4sbrowserless:job W18CF0FKU0R4YUPZ7NDMZ864B11FJ41O: Browser cleanup complete. +1msbrowserless:server Current workload complete. +1msbrowserless:chrome-helper Sending SIGKILL signal to browser process 482 +1msbrowserless:chrome-helper Removing temp data-dir /tmp/browserless-data-dir-eEZKKT +18msbrowserless:chrome-helper Garbage collecting and removing listeners +40msbrowserless:chrome-helper Temp dir /tmp/browserless-data-dir-eEZKKT removed successfully +11msbrowserless:server Health check stats: CPU 3%,0 MEM: 11%,11% +28sbrowserless:server Current period usage: {"date":1669647780850,"error":0,"rejected":0,"successful":1,"timedout":0,"totalTime":5959,"maxTime":5959,"minTime":5959,"meanTime":5959,"maxConcurrent":1} +0ms

如果你希望执行结果的成功/失败,展示的更明显一些,我们可以根据自己的实际情况,添加一些“成功/失败通知”(比如微信、飞书的通知 WebHook、PushOver 的服务等)。

或者索性借助 CI 工具对 CI 任务执行情况统计能力,进行任务执行情况汇总统计,也未尝不可。

其他

Playwright 和它的好兄弟 Puppeteer,以及 Browserless 除了进行自动化测试之外,其实还能做很多有趣的东西。

比如,在比较早的时候,我曾经分享了过一个用在运营场景的玩法《使用 Node.js 生成方便传播的图片》。你也可以拿它来生成招聘海报等等你能想到的东西,或者任何你觉得用 HTML、CSS、JS 或者浏览器端能力做起来比较省力的活儿。

毕竟偷懒是工程师的美德嘛(重要的话要说三遍)。

最后

时间不早啦,本篇文章先写到这里吧。

后面有机会我将会继续展开本文中尚未聊到,但是在生产过程中非常重要的:如何优化测试服务稳定性、如何提升测试程序的执行性能、如何和 CI/CD 基础技术设施结合使用,以及在折腾过程中的踩坑实战细节。

–EOF


我们有一个小小的折腾群,里面聚集了一些喜欢折腾的小伙伴。

在不发广告的情况下,我们在里面会一起聊聊软硬件、HomeLab、编程上的一些问题,也会在群里不定期的分享一些技术沙龙的资料。

喜欢折腾的小伙伴,欢迎阅读下面的内容,扫码添加好友。

  • 关于“交友”的一些建议和看法
  • 添加好友,请备注实名和公司或学校、注明来源和目的,否则不会通过审核。
  • 关于折腾群入群的那些事

本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2022年11月28日
统计字数: 5849字
阅读时间: 12分钟阅读
本文链接: https://soulteary.com/2022/11/28/playwrights-concise-introductory-tutorial-recording-automated-test-cases-and-using-it-with-docker.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_38498.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑密码忘了怎么解除?最简单操作的方法

可能很多人都遇到过这种情况&#xff1a;忘记了电脑密码。电脑密码忘了怎么解除&#xff1f;大多数人都不知道如何解决。下面就为大家分享一下电脑密码忘记怎么解决的方法&#xff0c;方法主要分为两种情况&#xff1a;一种情况是&#xff0c;电脑开机下忘记密码&#xff1b;另…

Cpp知识点系列-类型转换

前言 在做题的时候发现了需要用到类型转换&#xff0c;于是在这里进行了简单的记录。 历史原因&#xff0c;慢慢整理着发现类型转换也能写老大一篇文章了。又花了时间来梳理一下就成了本文了。 cpp 之前使用的环境是DEV-C 5.4&#xff0c;而对应的GCC版本太低了。支持c11需要…

智慧环卫管理系统解决方案(垃圾分类)

1.1 垃圾分类管理子系统 1.1.1 公众参与互动平台 可为客户量身打造微信公众号&#xff0c;搭建互动交流的平台&#xff0c;更好的调动居民参与垃圾分类的热情。 1.1.1.1 分类指导 将目前城市的垃圾处理情况、垃圾分类现状、分类的意义&#xff0c;以数据来说明垃圾分类的…

【设计】OOA、OOD、OOP

这三者都是 OO&#xff08;Object-Oriented&#xff09;领域的思想。 一般我们我们接到产品经理的需求后&#xff0c;开发阶段分这样几个步骤&#xff1a; 可行性预研阶段&#xff0c;此阶段评估需求是否合理&#xff0c;能否实现&#xff1b;OOA阶段&#xff0c;此阶段分析用…

语文课内外杂志语文课内外杂志社语文课内外杂志社2022年第14期目录

幼儿教育《语文课内外》投稿&#xff1a;cn7kantougao163.com 家园协同视域下幼儿心理危机的预防与干预对策 曹锭1-3 幼小衔接阶段幼儿时间观念的培养对策 陈晶晶4-6 有效支持 助力幼儿在书海中徜徉 胡玲珊7-9 东西部幼儿园结对帮扶,助力乡村教育扶贫——以广州市人民政府机关幼…

多线程(2)

文章目录前言 &#xff1a;1.Thread类 &#xff1a;1.1 Thread类常见的构造方法1.2 Thread的几个常见属性1.3 中断一个线程1.4 等待一个线程-join()1.5 获取当前线程引用1.6 休眠当前线程2.线程状态前言 &#xff1a; 简单回顾上文知识点 上文我们了解了 线程是为解决并发编程引…

Java数据审计工具:Envers and JaVers比较

在Java世界中&#xff0c;有两种数据审计工具&#xff1a;Envers和JaVers。 Envers已经存在了很长时间&#xff0c;它被认为是主流。 JaVers提供全新的方法和技术独立性。 如果您考虑哪种工具更适合您的项目&#xff0c;本文是一个很好的起点。 本文分为三个部分。首先&#x…

[附源码]计算机毕业设计springboot餐馆点餐管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【新知实验室-TRTC开发】实时音视频之欢度世界杯

目录 一、什么是TRTC 二、用5分钟跑通一个demo 1、开通腾讯云-TRTC 2、获取demo必须的两把钥匙 2.1输入应用名称 2.2下载对应的源码包&#xff08;手机、web、小程序等&#xff09; 2.3拿到钥匙 2.4完成 三、搭建一起看世界杯应用 1、解压源码&#xff08;耗时30S&#x…

[附源码]计算机毕业设计springboot房屋租赁系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

MySQL为自动编号的字段赋值

insert users values(NULL,ming,fasdfasdfasd,22,1); 或者 insert users values(DEFAULT,ming,fasdfasdfasd,22,1);

网络的根基

hi 大家好&#xff0c;上个周末带小伙伴&#xff0c;一起复习了一遍网络协议&#xff0c;对网络协议的核心知识进行梳理&#xff0c;希望大家早日掌握这些核心知识&#xff0c;打造自己坚实的基础&#xff0c;为自己目标慢慢积累&#xff0c;等到自己春天的到来。详细点击查看…

zabbix拓扑图和聚合图形

目录 一、环境准备 1、搭建zabbix基础环境 2、创建被监控主机 二、拓扑图 1、拓扑图作用 2、拓扑图绘制步骤 三、聚合图形 1、聚合图形的作用 2、创建聚合图形 一、环境准备 1、搭建zabbix基础环境 zabbix基础环境部署参照&#xff1a;zabbix基础环境部署_桂安俊kyli…

Day14--商品详情-渲染商品详情的数据并优化详情页的显示

提纲挈领&#xff1a; 那么如何在小程序中将这些html的字符串渲染成这莫好看的结构呢&#xff1f; 官方文档&#xff1a;【使用uni-ui组件库中的rich-text组件】 1.渲染商品详情信息 我的操作&#xff1a; 1》在页面结构中&#xff0c;使用 rich-text 组件&#xff0c;将带有…

计算机网络第五章知识点回顾(自顶向下)

1. 网络层控制面 1.1 网络层功能 1.2选路问题 选路问题的描述&#xff1a; 给定一组路由器和连接路由器的链路&#xff0c;寻找一条从源路由器到目的路由器的最佳路径。 1.3 什么是最佳路径&#xff1f; 1.4 图抽象 1.5 选路算法分类 1.6 链路状态&#xff08;LS&#xff0…

[附源码]计算机毕业设计springboot飞越青少儿兴趣培训机构管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

手把手教你构建一个前端路由

涉及知识点&#xff1a;location对象、history对象 文章目录基础概念什么是路由如何实现前端路由涉及问题前端路由实现方式1. hash方式2. history方式3. debug&#xff1a;本地起服务报错扩展&#xff1a;封装路由类Routerhashhistory基础概念 什么是路由 路由是一组映射关系…

51单片机学习笔记4 新建工程及点亮LED实战

51单片机学习笔记4 新建工程及点亮LED实战一、使用keil新建工程二、项目设置1. 点击魔术棒&#xff0c;钩选Output-Create Hex File2. 设置仿真器三、编写代码1. 尝试编译代码2. 点亮LED的代码3. GPIO引脚介绍4. GPIO内部结构P0端口&#xff1a;P1 端口四、软件仿真一、使用kei…

[附源码]SSM计算机毕业设计校园爱心支愿管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

台积电跪舔美国,日本却醒悟了而选择独立发展芯片产业

近期台积电大举包机10架将精英人才和设备转往美国引发争议&#xff0c;然而这个时候日本却选择了独立发展芯片产业的道路&#xff0c;摆脱美国的限制&#xff0c;显然日本清醒地认识到依赖美国不会有好结果。台积电之前还在左右摇摆&#xff0c;希望既能继续获得美国芯片的订单…