自动化测试|我为什么从Cypress转到了Playwright?

news2024/12/25 9:17:54

以下为作者观点:

早在2019年,我就开始使用Cypress ,当时我所在的公司决定在新项目中放弃Protractor 。当时,我使用的框架是Angular,并且有机会实施Cypress PoC。最近,我换了工作,现在正在使用React,在那里我也有机会实现Playwright PoC。

个人感觉,有了Angular和React的经验,我更倾向于使用data-testid属性进行测试。这让我能够在UI端到端测试中保持一致的方法,而且我没有观察到Angular和React应用程序在测试中存在任何显著差异。

注:在本文中,我使用了一个React应用程序作为Cypress和Playwright的示例。

这两个测试框架都提供什么?

Cypress和Playwright都能够提供出色的UI测试体验(还可以测试API)。它们的自动等待功能让开发人员更容易编写测试,在测试运行时提供可视化用户界面,还能生成测试截图和视频,并支持类型脚本。

这两个框架都支持可视化组件测试,但我不会在本文中讨论这个主题。

由于这两个框架提供的功能非常相似,因此我将剖析每个框架是如何实现以下方面的,以及它们如何影响开发人员体验/工作效率的:

编写测试所用的语法对学习曲线和每个框架的整体易用性起着至关重要的作用。包括但不限于使用自定义命令扩展框架和记录测试。
测试的执行和可维护性是影响开发人员对测试的信心和调试时间的重要因素,特别是在速度和稳定性方面。
测试报告在测试过程中发挥着重要作用,评估其设置的难易程度及其提供的信息水平对于这两个框架都至关重要。

我的Cypress使用体验

安装Cypress非常简单,只需依赖NPM就可以了。没过多久就遇到了使用 Cypress 时需要了解的复杂细节。以下是一些主要细节:

● 用于编写测试的语法

Cypress使用类似Promise的语法来编写测试。乍一看这似乎并不令人困惑,但开发人员倾向于认为,因为他们的API看起来像promise(承诺),所以其行为也像promise(async/await,异步/等待)。可悲的现实是,事实并非如此,这导致开发人员花费大量时间学习如何使用Cypress API,并使其适合他们特定的测试场景。

如果需要使用async/await,你有两种选择:要么将其封装在Cypress命令中,以便添加到Cypress命令链中;要么使用cypress-promise这样的库。下面是每个选项的示例:

// async-await.spec.ts
import promisify from 'cypress-promise';

function sleep(milliseconds: number) {
  return new Promise((resolve) => setTimeout(resolve, milliseconds));
}

async function asyncFunction(text: string) {
  console.log('started asyncFunction ' + text);
  await sleep(3000);
  console.log('finalized asyncFunction ' + text);
}

context('Async/Await Test', () => {
  beforeEach(() => {
    cy.visit('/');
  });

  it('convert promises into cypress commands, do not write tests using async/await', () => {
    cy.wrap(null).then(() => asyncFunction('first'));
    cy.wrap(null).then(() => asyncFunction('second'));
  });

  it('convert cypress commands to promises, should be able to code with async/await', async () => {
    const foo = await promisify(cy.wrap('foo'));
    const bar = await promisify(cy.wrap('bar'));
    expect(foo).to.equal('foo');
    expect(bar).to.equal('bar');
  });
});

● 测试报告

Cypress缺乏内置的测试报告功能,这意味着获取所有测试、测试持续时间以及故障截图和链接视频等附加元素的全面总结,可能是一个具有挑战性的繁琐过程。尽管在配置报告方面投入了大量精力,但在生成的报告中仍可能会出现缺少屏幕截图的情况。

图片

测试失败的基本 Cypress Mocha 测试报告

// package.json: example of cumbersome test reporting setup
  "scripts": {
    "-------------------- E2E Commands --------------------": "",
    "cypress:open": "nyc cypress open",
    "cypress:run": "npm-run-all -s --continue-on-error _clean _cypress-run:run _cypress-run:html",
    "-------------------- Supporting Commands --------------------": "",
    "_clean": "npx rimraf coverage cypress/output/junit cypress/output/mocha-json cypress/output/mocha-html/*.html cypress/output/mocha-html/*.json .nyc_output",
    "_coverage-report": "npx nyc report --reporter html",
    "_cypress-run:run": "nyc cypress run --headless --browser chrome",
    "_cypress-run:html:merge-json": "mochawesome-merge cypress/output/mocha-json/*.json > cypress/output/mocha-html/merged-mochawesome.json",
    "_cypress-run:html:gen-html-from-json": "marge cypress/output/mocha-html/merged-mochawesome.json -f cypress -o cypress/output/mocha-html -i true --charts true",
    "_cypress-run:html": "npm-run-all -s _cypress-run:html:merge-json _cypress-run:html:gen-html-from-json _coverage-report"
  },

● 如何运行head测试

Cypress会在其自己的浏览器应用程序中运行你的网络应用程序。它首先会打开一个页面,列出你的所有测试specs,然后你可以单击某个规范来运行该规范内的所有测试。我想补充的是,所有这一切都非常缓慢。此外,如果你只想在spec中运行一个测试,则需要将其标记为only,保存后只有该测试会自动重新加载。

图片

在Cypress浏览器内运行的应用程序

● 如何在headless运行中访问浏览器控制台日志

浏览器控制台日志只有在以标题形式(打开DevTools)运行测试时才可见。这意味着,如果你的测试在本地成功运行,但在CI管道上失败了,那么你要想把这些日志传到管道控制台就会很麻烦。幸运的是,有一个插件可以解决这个问题,但由于Cypress插件的工作方式,这不仅仅是一个即插即用的工作。

图片

只有在打开DevTools时才能看到浏览器控制台日志

// cypress/plugins/index.ts
interface Browsers {
 family: string;
 name: string;
}

interface LaunchOptions {
 args: string[];
}

const cypressPLugins = (on: unknown, config: unknown) => {
 require('@cypress/code-coverage/task')(on, config);
 // log console.* messages to the cypress console,
 // it helps when there are errors on the CI/CD pipeline
 require('cypress-log-to-output').install(on, consoleToLogConfig);
 require('@cypress/react/plugins/react-scripts')(on, config);
 // @ts-ignore
 on('before:browser:launch', (browser: Browsers, launchOptions: LaunchOptions) => {
 if (browser.family === 'chrome' || browser.name === 'chrome') {
 console.log('Adding chrome config...');
      launchOptions.args.push('--disable-dev-shm-usage');
      launchOptions.args.push('--lang=en');
    }
 return launchOptions;
  });
 return config;
};

export const consoleToLogConfig = (_type: unknown, event: { level: string; type: string }) => {
 // return true or false from this plugin to control if the event is logged on the cypress console
 // `type` is either `console` or `browser`
 // if `type` is `browser`, `event` is an object of the type `LogEntry`:
 //  https://chromedevtools.github.io/devtools-protocol/tot/Log/#type-LogEntry
 // if `type` is `console`, `event` is an object of the type passed to `Runtime.consoleAPICalled`:
 //  https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#event-consoleAPICalled

 // only show error events:
 return event.level === 'error' || event.type === 'error';
};

export default cypressPLugins;

● 调试测试(Debugging Tests)

Cypress中有几种不同的调试选项,由于Cypress命令是异步运行的,因此不能直接添加调试器(debugger)命令。

本质上,Cypress提供了2个有用的命令:debug()和pause()。前一个命令会向Cypress运行程序添加调试器命令,后一个命令则会在此时停止测试运行。两者都提供了检查DOM的能力,但只有使用 pause() 命令,你才能逐步检查测试中即将执行的每个Cypress 命令。

鉴于Cypress使用类似Promise的链接API,你可以将这些命令中的任何一个与任何Cypress命令链接起来:

cy.get([data-testid="username-input"]).type("my-username").pause();

图片

在Playwright中进行调试

● 测试并行化

Cypress不支持本地并行运行测试。有很多库可以帮助实现并行化,但是,这并不是一件容易的事。在我以前的公司中,我们尝试并行测试以提高流水线运行时间,但结果证明付出的努力太大,以至于我们取消了它的优先级。

副作用是,开发人员很少在本地运行完整的Cypress测试套件,他们只是等待来自管道的反馈。

● 速度

Cypress在headless和headed浏览器格式下运行时,速度都很慢,这是我们希望将测试并行化的主要原因。即使在本地运行,测试也非常慢。在开发测试时,当你修改文件时,测试会自动重新加载,即使在我的MacBook Pro上也需要几秒钟。

● 测试稳定性

Cypress以不稳定而闻名,主要是在CI/CD管道上,这导致开发人员花费大量时间去追寻ghosts。我看到开发人员通常采用的笨办法是在测试中添加 cy.wait(),并在CI/CD管道中添加重试。

● 自定义命令

如果你在测试中经常使用一些常用功能,那么你很可能想为此创建一个自定义Cypress命令。遗憾的是,添加此类命令既不直观,类型也不安全(除非你做了额外的工作):

// cypress/support/commands.ts
Cypress.Commands.add('getByTestId', (selector: string, ...args: unknown[]) => {
  return cy.get(`[data-testid=${selector}]`, ...args)
});

// cypress/typings/cypress.d.ts
declare namespace Cypress {
  interface Chainable {
    getByTestId(selector: string, ...args: unknown[]): Chainable;
  }
}

// you can now use this command in your test:
it('should type username in username input', () => {
  cy.getByTestId('username-input').type('my-username');
});

● 录音测试

Cypress现在提供Cypress Studio,目前这是一个实验性功能,我个人还没有尝试过。

我的Playwright使用体验

我从2023年初开始使用React,当时我的团队还没有任何UI测试。因此,我决定考虑引入Cypress。不过,我们也开始引入Web组件,并计划使用Storybook来记录和测试我们的Web组件。由于Storybook在幕后使用了Playwright,我研究了 Playwright可以提供什么。最初的诉求是:我的团队必须学习一个框架来测试Web组件和UI。

安装Playwright简直是轻而易举:不到一个小时,我就完成了所有测试。

● 编写测试所用的语法

编写Playwright测试就像编写普通的typescript代码一样简单,不需要学习特殊的API。最棒的是,你可以编写普通的async/await代码,因此你可以使用所有普通的typescript支持函数。比如:

import { test } from '@playwright/test';

test.describe('Playwright test with async/await', () => {
  function sleep(milliseconds: number) {
    return new Promise((resolve) => setTimeout(resolve, milliseconds));
  }

  async function asyncFunction(text: string) {
    console.log('started asyncFunction ' + text);
    await sleep(3000);
    console.log('finalized asyncFunction ' + text);
  }

  test('should open storybook and click around', async ({ page }) => {
    await page.goto('http://localhost:6006/');
    await page
      .getByRole('link', {
        name: 'Storybook 7.1.1 is available! Your current version is: 7.0.2 Dismiss notification',
      })
      .click();
    await page.getByRole('link', { name: 'Storybook' }).click();
    await page.locator('#internal-components-overview--docs').click();
  });

  test('should test the async methods used in previous example', async ({
    page,
  }) => {
    await asyncFunction('first');
    await asyncFunction('second');
  });
});

● 测试报告

这真是一个惊喜:我不需要做任何事情!

Playwright生成的开箱即用的报告非常棒。你还可以非常轻松地在多个浏览器上运行测试(只需更改配置,Playwright就会为你安装所需的浏览器)。

我将其配置为仅包含失败测试的跟踪信息、屏幕截图和视频;否则,就像 Cypress 一样,测试运行速度很慢。在下面的示例中,我们的第一次测试失败了。如果我们点击它,我们会得到以下信息:导致失败的异常、测试的哪些步骤失败、测试的视频以及完整的测试跟踪。

图片

Playwright HTML 报告概述

图片

测试失败的Playwright报告摘要

图片

Playwright测试轨迹

● 如何运行head测试

Playwright是微软开发的,所以他们当然提供了VS Code的插件。我自己是IntelliJ的用户,但我发现当我想运行Playwright测试时,我会切换到VS Code。

与Cypress不同的是,你不必启动任何程序就能运行一个或多个测试。只需在VS Code中打开代码,然后点击通常的单元测试绿色三角形,如果过去已经运行过测试,则点击绿勾/红X。你还可以选择打开浏览器或跟踪查看器。

开发人员在这里的体验非常棒。测试打开速度快,反应灵敏。

图片

● 如何在headless运行中访问浏览器控制台日志

与Cypress 一样,Playwright不会在Playwright运行的控制台中显示浏览器日志。为此,你可以扩展Playwright页面对象,将浏览器日志转发到控制台日志(还有其他方法,例如扩展测试对象本身)。

// utils/console.util.ts
export const configureLogForwarding = (page: Page) => {
  page.on('console', (msg) => {
    if (process.env.PLAYWRIGHT_LOG_TO_CONSOLE === 'true') {
      switch (msg.type()) {
        case 'info':
        case 'log': {
          // eslint-disable-next-line no-console
          console.log(`Log: "${msg.text()}"`);
          break;
        }
        case 'warning': {
          // eslint-disable-next-line no-console
          console.log(`Warning: "${msg.text()}"`);
          break;
        }
        case 'assert':
        case 'error': {
          // eslint-disable-next-line no-console
          console.log(`Error: "${msg.text()}"`);
          break;
        }
      }
    }
  });
};

// tests/demo-tests.spec.ts
test.describe('Playwright test with async/await', () => {
  test.beforeEach(async ({ page }) => {
    configureLogForwarding(page);
    hostAppNavigationPo = new HostAppNavigationPo(page);
    genericAssetModalPo = new GenericAssetModalPo(page);
  });
// ...

● 调试测试(Debugging Tests)

这是我最喜欢的功能之一。要调试测试,只需设置一个断点,然后右键单击绿色三角形/绿色滴点/红色x,再单击调试测试。浏览器将打开,运行将在断点处停止。从这里开始,就是开发人员习惯的正常调试会话。

图片

在Playwright中启动调试会话

图片

Playwright正在进行的调试会议

● 测试并行化

Playwright支持开箱即用的并行化(当然,你的被测系统当然必须能够支持并行运行的测试)。鉴于我们的CI/CD工具没有大量资源,因此速度很慢,因此我们在管道中关闭了并行测试。然而,当我编码时,我能够非常快速地在本地运行所有测试。当然,我们使用Playwright只有5个月左右,因此只有约80个测试。以下是一些非科学数据:~80个测试,在CI/CD中运行5分钟(1名工作人员),本地运行2分钟(1名工作人员),本地运行55秒(5名工作人员)。

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  /* other configuration... */
  /* Opt out of parallel tests on CI. */
  workers: process.env.CI ? 1 : undefined,
  /* Run tests in spec files in parallel */
  fullyParallel: true,
});

● 速度

当以headless形式运行等效测试时(就像在CI/CD管道中一样),Playwright比Cypress快约1.5倍。

此外,Playwright能够在不到一秒的时间内在浏览器上启动测试(在我的MacBook Pro上)。这意味着我可以随时以任何规格运行任何测试,而无需启动Playwright服务器等。与Cypress不同的是,你必须先启动Cypress UI,然后导航到你想在该UI中运行的测试。

这为开发者带来了绝佳的体验!

● 测试稳定性

过去5个月,我们一直在编写测试,还没有遇到任何不稳定的情况,也无需在测试中使用任何等待或休眠。由于我已不在原来使用Cypress的公司工作,我很难确定将那些不稳定的测试迁移到Playwright是否会使其稳定。

● 自定义命令

Playwright提供了一种扩展基础测试的方法,这样就可以在测试过程中轻松访问自定义命令和/或页面对象。这种模式简单易用、直观且类型安全。Playwright示例:

// my-test.ts
import { test as base } from '@playwright/test';
import { TodoPage } from './todo-page';

export type Options = { defaultItem: string };

// Extend basic test by providing a "defaultItem" option and a "todoPage" fixture.
export const test = base.extend<Options & { todoPage: TodoPage }>({
  // Define an option and provide a default value.
  // We can later override it in the config.
  defaultItem: ['Do stuff', { option: true }],

  // Define a fixture. Note that it can use built-in fixture "page"
  // and a new option "defaultItem".
  todoPage: async ({ page, defaultItem }, use) => {
    const todoPage = new TodoPage(page);
    await todoPage.goto();
    await todoPage.addToDo(defaultItem);
    await use(todoPage);
    await todoPage.removeAll();
  },
});

// example.spec.ts
import { test } from './my-test';

test('test 1', async ({ todoPage }) => {
  await todoPage.addToDo('my todo');
  // ...
});

● 录制测试

Playwright提供了使用VS Code插件录制UI测试的选项。你所需要做的就是按下Record new按钮,Playwright就会打开一个浏览器。然后输入网络应用程序的URL并开始点击。Playwright录制的最大优点是,如果存在data-testid选择器(await page.getByTestId(‘dialog-title’); ),它就会选择该选择器。

图片

Playwright 还有许多其他优点,我在本文中没有介绍,主要是因为我没有大量使用这些方面,但这里有一些示例:

● iFrames

Playwright可以与iFrames兼容,使用起来非常流畅。在我目前的工作中,我们正在使用iFrames,但在我之前的工作中(当时我在Cypress工作),我们没有使用 iFrames。不过,据我所知,你需要安装Cypress插件才能测试iFrames。

● Web-app服务器

Cypress和Playwright都要求你的应用程序在运行时才能进行测试。对Cypress的一个普遍要求是,该框架能够在运行测试前启动被测系统。我个人在本地和在CI/CD管道中运行测试时,应用程序始终处于运行状态。不过,Playwright也听到了开发人员的愿望:

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  // Run your local dev server before starting the tests.
  webServer: {
    command: 'npm run start',
    url: 'http://127.0.0.1:3000',
    reuseExistingServer: !process.env.CI,
  },
});

● Forbid only关键字

一个常见的用例是,当开发人员想要运行单个测试时,他们将其标记为only. 不幸的是,他们经常忘记在提交之前删除它。Playwright附带了一个配置来检测这一点,而使用Cypress时我们必须添加eslint规则。

// playwright.config.ts
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  /* Fail the build on CI if you accidentally left test.only in the source code. */
  forbidOnly: !!process.env.CI,
});

// example.spec.ts
test.describe('Playwright test with async/await', () => {

  test.only('should test the async methods used in previous example', async ({
    page,
  }) => {
    await asyncFunction1();
    await asyncFunction2();
  });

// more tests...

● 多页面

Cypress在其自己的Web应用程序内运行Web应用程序,这会限制Cypress一次只能在一页上运行测试。另一方面,Playwright可在每个浏览器中打开多个BrowserContext和/或多个页面,所有这些页面都有不同的网站/域等,并可在所有这些页面上运行测试。

● 多语言支持

在Cypress中,您可以选择使用JavaScript或TypeScript编写测试。然而,在Playwright中,编写测试的语言选项更加多样化。你可以选择使用JavaScript、TypeScript、Java、Python或 .NET编写测试,从而为开发人员提供了更大的灵活性,让他们可以使用自己喜欢的编程语言来实现测试自动化。

结论

多年来,我一直是Cypress的粉丝,也是UI测试的坚定拥护者,现在要开始使用一个我不确定是否会像Cypress一样优秀的新框架,这并不是一个容易的决定。尽管如此,我还是惊喜地发现Playwright不仅达到了Cypress的预期,而且在我能想到的所有方面都超过了Cypress。

最后,Cypress和Playwright的开发者社区都相当庞大。尽管Cypress仍然更受欢迎,但随着越来越多的开发者发现Playwright的开发者体验是如此令人惊叹,Playwright社区也在快速发展。

在这里插入图片描述

截至2023年7月29日的对比数据

建议任何已经在使用Cypress或正在考虑进入UI测试领域的人,将Playwright作为一个值得考虑的选择。

最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你! 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot自定义更换启动banner动画

springboot自定义更换启动banner动画 文章目录 springboot自定义更换启动banner动画 &#x1f4d5;1.新建banner&#x1f5a5;️2.启动项目&#x1f516;3.自动生成工具&#x1f9e3;4.彩蛋 &#x1f58a;️最后总结 &#x1f4d5;1.新建banner 在resources中新建banner.txt文…

C#——多线程之异步调用容易出现的问题

C#——多线程之异步调用容易出现的问题 Q1&#xff1a;For中异步调用函数且函数输入具有实时性 Q1&#xff1a;For中异步调用函数且函数输入具有实时性 在项目进行过程中&#xff0c;发现For中用异步调用带有输入参数的函数时&#xff0c;会由于闭包特性&#xff0c;以及Task.…

ssm+vue的公司安全生产考试系统(有报告)。Javaee项目,ssm vue前后端分离项目。

演示视频&#xff1a; ssmvue的公司安全生产考试系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;ssm vue前后端分离项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结…

C#从零搭建微信机器人(二)分词匹配组件【jieba】的使用

上篇文章我们讲解了微信机器人的环境搭建及演示&#xff0c;这期我们来说一下其中在模糊匹配搜索时用到的Segement子项目&#xff0c;也就是其中的中文分词匹配器。 一、原理介绍&#xff1a; 其实这个子项目中的分词插件和solr的IK分词器类似&#xff0c;都是可以支持将一句…

TP4066L是一款完整的单节锂离子电池采用恒定电流/恒定电压线性充电器。

TP4066L 采用ESOP8/DFN2*2-8封装 1A线性锂离子电池充电器 描述&#xff1a; TP4066L是一款完整的单节锂离子电池采用恒定电流/恒定电压线性充电器。其底部带有散热片的ESOP8DFN2*2-8封装与较少的外部元件数目使得TP4066L成为便携式应用的理想选择。TP4066L可以适合USB电源和适…

桐庐县数据资源管理局领导一行莅临美创科技并带来感谢信

11月23日&#xff0c;浙江桐庐县数据资源管理局党组成员、副局长朱勃一行到访美创科技总部参观交流&#xff0c;并带来感谢信&#xff0c;对美创圆满完成护航亚运政务外网数据网站安全保障工作表示充分肯定。美创科技联合创始人、副总裁胡江涛等进行热情接待并开展交流座谈。 图…

微信ipad协议8.0.37/8.0.40新版本

功能如下&#xff0c;如有定制功能请在官网联系我们。 登录 创建新设备 获取登录er维码 执行登录 注销登录 消息 消息回调 消息撤回 发送app类型消息 发送小程序 发送CDN文件 发送CDN图片 发送CDN视频 发送emoji 发送文件 发送图片 发送链接 发送消息 发送视频 发送语音 …

2021年全国a级景区数据,shp+csv数据均有

大家好~这周将和大家分享关于文化旅游和城乡建设相关的数据&#xff0c;希望大家喜欢~ 今天分享的是2021年全国a级景区数据&#xff0c;数据格式有shpcsv&#xff0c;几何类型为点&#xff0c;已经经过清洗加工&#xff0c;可直接使用&#xff0c;以下为部分字段列表&#xff…

无人机遥控器方案定制_MTK平台无人设备手持遥控终端PCB板开发

随着科技的不断发展和无人机技术的逐步成熟&#xff0c;无人机越来越受到人们的关注。作为一种高新技术&#xff0c;无人机的应用范围不断拓展&#xff0c;包括农业、环境监测、城市规划、运输物流等领域。同时&#xff0c;无人机的飞行控制技术也得到了不断的优化和提升。 早…

前端管理制度

数据运营中心的管理形式&#xff1a; 数据运营中心的管理形式 竖向是各小组 横向是项目管理 负责人的定位&#xff1a; 只是工作的内容不同&#xff0c;没有上下级之分 帮助组员找到适合的位置&#xff0c;帮助大家解决问题&#xff0c;给大家提供资源 前端组的工作形式&am…

Doris-Routine Load(二十七)

例行导入&#xff08;Routine Load&#xff09;功能为用户提供了一种自动从指定数据源进行数据导入的功能。 适用场景 当前仅支持从 Kafka 系统进行例行导入&#xff0c;使用限制&#xff1a; &#xff08;1&#xff09;支持无认证的 Kafka 访问&#xff0c;以及通过 SSL 方…

二维码智慧门牌管理系统:实现高效信息管理

文章目录 前言一、 功能升级优势 前言 随着科技的飞速发展和人们生活节奏的加快&#xff0c;传统的门牌管理系统已经不再适应现代社会的需求。为了解决这一问题&#xff0c;全新的二维码智慧门牌管理系统升级解决方案应运而生&#xff0c;为用户带来前所未有的便捷与高效。 一…

1m照片手机怎么拍?一分钟解决!

我们都知道现在的手机像素特别好&#xff0c;随便拍一张照片都是2-3MB&#xff0c;有时候上课或者会议要拍很多照片&#xff0c;这些照片其实又不需要如此清晰&#xff0c;就会特别占内存&#xff0c;下面就向大家介绍三种好用的办法。 方法一&#xff1a;拍完照后手机截图进行…

【开源】基于JAVA的海南旅游景点推荐系统

项目编号&#xff1a; S 023 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S023&#xff0c;文末获取源码。} 项目编号&#xff1a;S023&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户端2.2 管理员端 三、系统展示四…

训练 CNN 对 CIFAR-10 数据中的图像进行分类

1. 加载 CIFAR-10 数据库 import keras from keras.datasets import cifar10# 加载预先处理的训练数据和测试数据 (x_train, y_train), (x_test, y_test) cifar10.load_data() 2. 可视化前 24 个训练图像 import numpy as np import matplotlib.pyplot as plt %matplotlib …

【Java开发基础】intellij IDEA快速配置JDBC驱动连接MySQL数据库并查询数据,其实真的很简单,我5分钟就学会了!

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;web开发者、设计师、技术分享博主 &#x1f40b; 希望大家多多支持一下, 我们一起学习和进步&#xff01;&#x1f604; &#x1f3c5; 如果文章对你有帮助的话&#xff0c;欢迎评论 &#x1f4ac;点赞&a…

多功能音乐沙漏的设计与实现

【摘要】随着当今社会快节奏生活的发展&#xff0c;当代大学生越来忽视时间管理的重要性&#xff0c;在原本计划只看几个视频只玩几个游戏的碎片化娱乐中耗费了大量的时光&#xff0c;对于自己原本的学习生活产生了巨大的影响。为更加有效的反映时间的流逝&#xff0c;特设计该…

canvas基础:绘制线段,绘制多边形

canvas实例应用100 专栏提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。 canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重要的帮助。 文章目录 使用…

TDA4开发环境Docker化

文章目录 背景1. TDA4X Linux SDK编译环境镜像构建1.1 安装SDK1.2 验证制卡1.2.1 出现的问题:1.3 验证编译1.3.1 出现的问题2. TDA4X Linux-RT SDK编译环境镜像构建2.1 安装SDK2.2 出现的问题参考背景 开始阅读本篇前,假设你已经对docker有了一定了解,且有过docker换件搭建…

优思学院|5S不只是清洁,但却离不开清洁!

很多说5S不止是清洁和搞卫生那么简单&#xff0c;相信有正规地学习过5S的人都应该深切了解。 不过&#xff0c;5S之中的确包括了清理、清洁的步骤&#xff0c;5S&#xff0c;也被称为“五常法则”或“五常法”&#xff0c;它包含了&#xff1a; 整理&#xff08;SEIRI&#x…