网易首页 > 网易号 > 正文 申请入驻

Cucumber.js 教程和 Selenium JavaScript 示例

0
分享至

本 Cucumber.js 教程将帮助您在基于云的 Selenium Grid 中使用 Selenium 和 JavaScript 自动化浏览器测试,该网格包含 2000 多个移动和桌面浏览器。

我们的自动化测试人员同事经常质疑使用 Cucumber.js 等 BDD 框架的相关性。许多人认为这只是在他们的桌子上增加了更多的工作。但是,使用 BDD 框架有其自身的优势,这些优势可以帮助您使 Selenium 测试自动化走得更远。不要旁观,这些 BDD 框架可以帮助您的所有利益相关者轻松解释测试自动化脚本背后的逻辑。利用 Cucumber.js 进行 Selenium JavaScript 测试可以帮助您指定任何非程序员都容易理解的验收标准。它还可以帮助您快速评估 Selenium 测试自动化套件中隐含的逻辑,而无需浏览大量代码。
使用给定的时间结构,像Cucumber.js这样的行为驱动开发框架使测试更容易理解。为了说明这一点,让我们来看一个小场景。如果 ATM 运行良好,您必须对其进行测试。我们将编写条件,假设帐户余额为 1,000 美元,卡有效,并且机器中有足够的钱。当账户持有人要求$200时,取款机应取款$200,账户余额应为$800,并退卡。
在本 Cucumber.js 教程中,我们将深入了解如何使用 Cucumber.js 对 Selenium JavaScript 测试进行第一个自动化测试的设置、安装和执行。
什么是 Cucumber.js 以及它为何如此受欢迎?
让我们从关于框架的简短介绍开始我们的 Cucumber.js 教程。Cucumber.js 是一个非常健壮和有效的 Selenium JavaScript 测试框架,适用于行为驱动程序开发过程。这个测试库提供了与 Selenium 的轻松集成,并为我们提供了用即使是外行也能理解的简单语言来定义测试的能力。Cucumber.js Selenium JavaScript 测试库遵循 given-when-then 结构,有助于以通俗易懂的语言表示测试,这也使我们的测试成为交流和协作的一个点。此功能提高了测试的可读性,因此有助于更好地理解每个用例。它被开发人员用于单元测试,但主要用于集成和端到端测试。而且,
为 Selenium Javascript 测试设置 Cucumber.js
因此,在我们继续我们的 Cucumber.js 教程之前,要开始使用 Cucumber 编写和执行我们的自动化测试脚本,我们需要使用 Cucumber.js 框架设置我们的系统并安装所有必要的库和包以开始 Selenium JavaScript测试。
Node JS 和 Node Package Manager (npm):这是基础包,对于任何 Selenium Javascript 测试框架来说都是最重要的。它可以通过 npm 管理器下载,即从 nodejs.org 官方网站安装节点包管理器,或者使用从此处网站下载的适用于 Mac OS、Windows 或 Linux 的不同操作系统的包安装程序。我们可以在命令行中执行npm命令,查看系统是否正确安装。
Cucumber.js 库模块:执行测试所需的下一个先决条件是 Cucumber.js 库。我们需要 Cucumber.js 包作为开发依赖项。在系统上成功安装和验证 Node.js 后,我们将使用它提供的节点包管理器,即 npm,在 npm 存储库中安装 Cucumber.js 库包。
因此,为了安装最新版本的 Cucumber.js 模块,我们将使用 npm 命令,如下所示
$ npm install -g cucumber
and
npm install --save-dev cucumber
这里的参数g表示模块全局安装,即不限制当前项目使用模块,也可以通过命令行工具访问。使用参数执行的命令–save-dev会将Cucumber可执行文件放在基目录,即./node_modules/.bindirectory中,使用cucumber关键字执行我们命令行工具中的命令。
Java – SDK:由于所有 Selenium 测试框架在内部都使用 Java,接下来,我们将继续并在我们的系统上安装 Java Development Kit。建议使用6.0及以上版本的JDK,并设置/配置Java的系统环境变量。
Selenium Web Driver:要使系统浏览器自动化,我们需要使用以下 npm 命令安装 Selenium Web Driver Library。在大多数情况下,它会在安装其他库时作为依赖项自动安装在我们的 npm node_modules 基本目录中。
$ npm install selenium-webdriver
浏览器驱动程序:最后,需要安装浏览器驱动程序。它可以是我们想要执行测试场景的任何浏览器,因此需要安装相应的驱动程序。这个可执行文件需要添加到我们的 PATH 环境变量中,并放在同一个 bin 文件夹中。在这里,我们正在安装 chrome 驱动程序。
这是文档的链接,我们可以在其中找到并下载与我们的浏览器版本相匹配的版本。
$ npm install -g chromedriver
使用 Cucumber.js 测试框架?
现在我们已经为我们的 Cucumber.js 教程设置了我们的系统,我们将继续创建我们的项目结构并创建一个名为cucumber_test. 然后我们将创建两个子文件夹,即 feature 和step_definition,其中将包含为我们的功能和步骤定义编写的相应脚本。
$ mkdir 步骤定义
最后,该文件夹将在包的基目录中生成一个 package.json 文件,并保存这些模块的所有开发依赖项。对 package.json 文件做的另一件重要事情是在脚本参数中添加测试属性。
{
"scripts": {
"test": "./node_modules/.bin/cucumber-js"
}
}
通过将此代码段添加到我们的 package.json 文件中,我们只需在命令行中键入“npm test”,即可从命令行运行所有 Cucumber 测试。我们最终的项目文件夹结构如下所示。
cucumber_test
| - - feature
| - - feature_test.feature
| - - step_definition
| - - steps_def.js
| - - support
| - - support.js
| - - package.json
下面是一个Cucumber.js项目的工作流程:
我们首先编写一个.feature包含场景的文件,每个场景都定义了给定的“何时”结构。
接下来,我们写下步骤定义文件,这些文件通常定义与场景中的步骤匹配的函数。
此外,我们根据我们的要求实现这些功能,或者使用 Selenium 驱动程序在浏览器中自动执行测试。
最后,我们通过执行文件夹中的 Cucumber.js 可执行文件来运行测试node_modules/.bin。
运行我们的第一个 Cucumber.js 测试脚本
本 Cucumber.js 教程的下一步是执行示例应用程序。我们将首先创建一个名为 script 的项目目录cucumber_test,然后创建一个名为 script 的子文件夹,single_test.js其中包含一个测试脚本名称。
然后我们将在文件的帮助下添加一个场景.feature。当我们指示 Cucumber.js 运行功能文件时,它将提供给我们的应用程序。最后,Cucumber.js 框架将解析该文件并调用与特征文件中的信息相匹配的代码。
对于我们的第一个测试场景,我们将从一个非常简单的基于浏览器的应用程序开始,在访问 Selenium 官方主页时,我们可以通过单击搜索按钮进行搜索。
请记下package.json我们将在即将进行的演示中使用的文件。
package.json
package.json 文件包含与项目相关的所有配置以及项目设置所必需的某些依赖项。请务必注意,此文件中的定义用于执行脚本,因此它充当我们的项目描述符。

{
"name": "Cucumber.js Javascript test with Selenium",
"version": "1.0.0",
"description": "CucumberJS Tutorial for Selenium JavaScript Testing",
"main": "index.js",
"scripts": {
"test": "./node_modules/.bin/cucumber-js"
},
"repository": {
"type": "git",
"url": ""
},
"author": "",
"license": "ISC",
"description": {
"url": ""
},
"homepage": "",
"dependencies": {
"assert": "^1.4.1",
"chromedriver": "^2.24.1",
"cucumber": "^1.3.0",
"geckodriver": "^1.1.3"
},
"devDependencies": {
"selenium-webdriver": "^3.6.0"
}
}


现在,项目的第一步是定义我们要实现的功能,即在这个文件中;我们将描述我们希望从我们的应用程序中获得的行为,在我们的例子中是访问网站。此功能允许浏览器检查元素。因此,我们将使用代码更新我们的功能文件。下面是我们的功能文件的样子,其中包含给定的时间和场景。
feature_test.feature
现在我们将拥有第一个基本场景,用于访问功能文件中定义的网站,然后是其他场景。这些场景将遵循给定的“何时”模板。
给定:它设置初始上下文或先决条件。
何时:这类似于场景中应该发生的事件。
然后:这是测试场景的预期结果。
steps_def.js
现在继续定义步骤。在这里,我们定义了与我们的场景中的步骤相匹配的功能,以及当场景被触发时它们应该执行的操作。
/* This Cucumber.js tutorial file contains the step definition or the description of each of the behavior that is expected from the application */
'use strict';
const { Given, When, Then } = require('cucumber');
const assert = require('assert')
const webdriver = require('selenium-webdriver');
// // The step definitions are defined for each of the scenarios // //
// // The “given” condition for our test scenario // //
Given(/^I have visited the Selenium official web page on "([^"]*)"$/, function (url, next) {
this.driver.get('https://www.selenium.dev').then(next);
});
// // The “when” condition for our test scenario // //
When(/^There is a title on the page as "SeleniumHQ Browser Automation" "([^"]*)"$/, function (titleMatch, next) {
this.driver.getTitle()
.then(function(title) {
assert.equal(title, titleMatch, next, 'Expected title to be ' + titleMatch);
// // The “then” condition for our test scenario // //
Then(/^I should be able to click Search in the sidebar $/, function (text, next) {
this.driver.findElement({ id: 'searchText' }).click();
this.driver.findElement({ id: 'searchText' }).sendKeys(text).then(next);
});
这里需要注意的一件重要事情是,如果我们执行测试时只写入 .feature 文件而没有其他任何内容,那么 Cucumber 框架将抛出错误并提示我们定义步骤。它指出虽然我们已经定义了功能,但缺少步骤定义,它会进一步建议我们编写代码片段,将上面定义的短语变成具体的动作。
support.js
support和hook文件与步骤定义一起使用以初始化变量并执行某些验证。
// // This Cucumber.js tutorial support file to perform validations and initialization for our app // //
const { setWorldConstructor } = require('cucumber')
const { seleniumWebdriver } = require('selenium-webdriver');
var firefox = require('selenium-webdriver/firefox');
var chrome = require('selenium-webdriver/chrome');
class CustomWorld {
constructor() {
this.variable = 0
}
function CustomWorld() {
this.driver = new seleniumWebdriver.Builder()
.forBrowser('chrome')
.build();
}
setWorldConstructor(CustomWorld)
module.exports = function() {
this.World = CustomWorld;
this.setDefaultTimeout(30 * 1000);
};
hook.js
它在测试执行完成时释放驱动程序。

module.exports = function() {
this.After(function() {
return this.driver.quit();
});
};


最后,当我们执行测试时,我们可以在命令行中看到我们的测试已成功执行。
$ npm test
命令行
现在让我们看一下另一个示例,该示例将在 google 上执行搜索查询并验证网站的标题以断言是否在浏览器中启动了正确的网站。
feature_test2.feature
功能:检查访问 Google 搜索网站的功能
场景:访问 Google.com 的主页假设我已经访问了 Google 主页。然后我应该能够在标题栏中看到 Google。
steps_def2.js

/* This Cucumber.js Tutorial file contains the step definition or the description of each of the behavior that is expected from the application which in our case is the webpage that we are visiting for selenium javascript testing .*/
var assert = require('assert');
// // This scenario has only “given” and “then” condition defined // //
module.exports = function () {
this.Given(/^I have visited the Google homepage$/, function() {
return this.driver.get('http://www.google.com');
});
this.Then(/^I should be able to see Google in title bar$/, function() {
this.driver.getTitle().then(function (title) {
assert.equal(title, "Google");
return title;
});
});
};

support2.js

// This Cucumber.js tutorial support file is used to perform validations and initialization for our application //
var seleniumWebdriver = require('selenium-webdriver');
var firefox = require('selenium-webdriver/firefox');
var chrome = require('selenium-webdriver/chrome');
function CustomWorld() {
this.driver = new seleniumWebdriver.Builder()
.forBrowser('chrome')
.build();
}
module.exports = function() {
this.World = CustomWorld;
this.setDefaultTimeout(30 * 1000);
};


hooks2.js

module.exports = function() {
this.After(function() {
return this.driver.quit();
});
};


同样,当我们执行测试时,我们可以在命令行中看到我们的测试已成功执行。
$ npm test
测试场景 1

荣誉!您已经成功执行了第一个用于 Selenium 测试自动化的 Cucumber.js 脚本。但是,本 Cucumber.js 教程并没有就此结束!现在您已经熟悉了 Selenium 和 Cucumber.js,我希望您考虑一下这里的可伸缩性问题。
到目前为止,您已经在您的操作系统上成功执行了 Cucumber.js 脚本。但是,如果您要执行自动化浏览器测试,您将如何在数百种不同的浏览器 + 操作系统组合上测试您的 Web 应用程序?
您可以继续构建 Selenium 网格以利用并行测试。但是,随着测试需求的增长,您将需要扩展 Selenium Grid,这意味着要在硬件上花费大量资金。此外,每个月都会在市场上推出新的浏览器或设备。要通过它们测试您的网站,您必须建立自己的设备实验室。
所有这些都可能会花费您维护内部 Selenium 基础设施的金钱和时间。所以,你可以做什么?
您可以利用云端的 Selenium 网格。选择基于云的 Selenium Grid 而不是本地设置有多种优势。最关键的优势是它使您免于维护内部 Selenium 基础设施的麻烦。它将为您节省安装和管理不必要的虚拟机和浏览器的工作。这样,您需要关注的就是运行您的 Selenium 测试自动化脚本。让我们尝试在云上的在线 Selenium 网格上执行我们的 Cucumber.js 脚本。
在在线 Selenium 网格上运行 Cucumber.js 脚本
现在是我们通过在跨浏览器测试云 LambdaTest 上执行测试脚本的培训来体验云 Selenium Grid 的时候了。
LambdaTest 允许您在云端托管的 3000 多种浏览器和操作系统组合上测试您的网站。不仅可以提高您的测试覆盖率,还可以节省您在整个测试执行过程中的时间。
要在 LambdaTest Selenium Grid 上运行相同的脚本,您只需稍微调整一下 Selenium JavaScript 测试脚本。正如您现在想要为 Remote WebDriver 指定中心 URL,它将在我们的 Selenium Grid 上执行您的脚本。添加用户名和访问密钥令牌。为此,我们必须在配置文件中添加访问密钥令牌和用户名详细信息,即cred.conf.jsconf 目录中的文件。用户名和访问密钥令牌可以通过两种方式导出,如下所述。
cred.conf.js

exports.cred = {
username: process.env.LT_USERNAME || 'rahulr',
access_key: process.env.LT_ACCESS_KEY || 'AbcdefgSTAYSAFEhijklmnop'
}


或者,可以使用如下所示的命令轻松导出用户名和访问密钥令牌。

export LT_USERNAME=irohitgoyal
export LT_ACCESS_KEY= AbcdefgSTAYSAFEhijklmnop


接下来,我们将查看功能文件。我们将在 Google Chrome 浏览器上执行我们的测试。在我们的测试用例中,我们将打开 LambdaTest 网站以对其执行某些操作,例如启动搜索引擎、验证内容等。因此,我们的目录结构将非常简单,如下所示:
feature_test.feature


因此,在我们的测试场景中,所需的功能类将类似于以下内容:

const desiredCapabilities = {
'build': 'Cucumber-JS-Selenium-Webdriver-Test', // the build name that is to be display in the test logs
'browserName': 'chrome', // the browser that we would use to perform test
'version':'74.0', // the browser version that we would use.
'platform': 'WIN10', // The type of the Operating System that we would use
'video': true, // flag to check whether to capture the video selenium javascript testing
.
'network': true, // flag to check whether to capture the network logs
'console': true, // flag to check whether to capture the console logs
'visual': true // flag to check whether to the capture visual for selenium javascript testing
};

有了那个集合,我们现在看看步骤定义和黄瓜 runner.js。
step_def.js

/*
This Cucumber.js tutorial file contains the step definition or the description of each of the behavior that is expected from the application which in our case is the webpage that we are visiting.
It is aligned with the feature file and reads all the instructions from it and finds the matching case to execute it for selenium javascript testing
.
*/
'use strict';
const assert = require('cucumber-assert');
const webdriver = require('selenium-webdriver');
module.exports = function() {
this.When(/^I visit website of Google on "([^"]*)"$/, function (url, next) {
this.driver.get('https://google.com ').then(next);
});
this.When(/^the homepage has the field with "Google Search" is present
$/, function (next) {
this.driver.findElement({ name: 'li1' })
.click().then(next);
});
this.When(/^the homepage has the field with "I’m Feeling Lucky" is present $/, function (next) {
this.driver.findElement({ name: 'li3' })
.click().then(next);
});
this.When(/^I move the cursor and select the textbox to make a search on Google $/, function (text, next) {
this.driver.findElement({ id: 'buttonText' }).click();
this.driver.findElement({ id: 'buttonText' }).sendKeys(text).then(next);
});
this.Then(/^click the "Google Search" on the text box "([^"]*)"$/, function (button, next) {
this.driver.findElement({ id: button }).click().then(next);
});
this.Then(/^I must see title "Google" on the homepage "([^"]*)"$/, function (titleMatch, next) {
this.driver.getTitle()
.then(function(title) {
assert.equal(title, titleMatch, next, 'Expected title to be ' + titleMatch);
});
});
};

cucumber-runner.js

#!/usr/bin/env/node
//
It resembles our runner file for parallel tests. This file is responsible to create multiple child processes, and it is equal to the total number of test environments passed for selenium javascript testing
.
//
let childProcess = require ('child_process') ;
let configFile = '../conf/' + ( process.env.CONFIG_FILE || 'single' ) + '.conf.js';
let config = require (configFile ).config;
process.argv[0] = 'node';
process.argv[1] = './node_modules/.bin/cucumber-js';
const getValidJson = function(jkInput) {
let json = jkInput;
json = json.replace(/\\n/g, "");
json = json.replace('\\/g', '');
return json;
};
let lt_browsers = null;
if(process.env.LT_BROWSERS) {
let input = getValidJson(process.env.LT_BROWSERS);
lt_browsers = JSON.parse(input);
}
for( let i in (lt_browsers || config.capabilities) ){
let env = Object.create( process.env );
env.TASK_ID = i.toString();
let p = childProcess.spawn('/usr/bin/env', process.argv, { env: env } );
p.stdout.pipe(process.stdout);
}


现在,由于我们的测试脚本已准备好在云网格中执行,我们需要做的最后一件事是使用以下命令从基础项目目录运行测试:
$ npm test
此命令将验证测试用例并在我们定义的所有测试组中执行我们的测试套件。如果我们打开 LambdaTest Selenium Grid 并导航到自动化仪表板,我们可以检查用户界面是否显示测试成功运行并通过并获得积极结果。
以下是示例屏幕截图:

测试样品
不要忘记利用并行测试
使用 Selenium 进行并行测试可以帮助您显着缩短测试周期。想象一下,如果我们至少要执行 50 个测试用例,并且每个测试用例的平均运行时间为 1 分钟。理想情况下,执行测试套件大约需要 50 分钟。但是,如果我们在 2 个并行并发会话中执行 2 个测试用例,则总测试时间会下降到 25 分钟。因此,我们可以看到测试时间急剧减少。要使用 Selenium 对此 Cucumber.js 教程执行并行测试,请执行以下命令$ npm run parallel。
总结
Cucumber.js 为我们提供了以一种每个人都容易阅读的方式编写测试的能力。使框架非常灵活,并使我们能够创建人类可读的用户需求描述,作为 Web 应用程序测试的基础。使用 Cucumber.js,我们可以在浏览器上与我们的网页进行交互,并通过使用 Selenium Grid 进行各种断言来验证我们执行的更改是否实际反映在我们的 Web 应用程序中的每个浏览器操作系统组合上。尽管如此,Cucumber.js 还可以做很多事情。由于这个测试框架是在 Selenium 接口上开发的,它赋予我们在 Selenium JavaScript 测试方面的无限能力。让我们知道您是否喜欢这个 Cucumber.js 教程,以及您是否希望我们撰写任何主题。快乐测试,保持安全!

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
苟仲文5年前发言:中国足球一直在低水平徘徊,我们也很着急

苟仲文5年前发言:中国足球一直在低水平徘徊,我们也很着急

懂球帝
2024-05-30 16:04:10
踩坑了!撤销ST涨停板涌进2.3亿,结果今天跌停,全部被一锅端

踩坑了!撤销ST涨停板涌进2.3亿,结果今天跌停,全部被一锅端

惜别的海岸
2024-05-30 14:49:36
雅迪、爱玛多个品牌禁止在北京销售,70%配置锂电池,车主怎么办

雅迪、爱玛多个品牌禁止在北京销售,70%配置锂电池,车主怎么办

电动车的那些事儿
2024-05-30 06:25:32
国家安全部:境外间谍情报机关长期觊觎我国稀土产业发展成果 部分境外企业引诱勾结中方人员大量走私稀土管制类物项

国家安全部:境外间谍情报机关长期觊觎我国稀土产业发展成果 部分境外企业引诱勾结中方人员大量走私稀土管制类物项

每日经济新闻
2024-05-30 11:32:23
都显怀还不能让你释怀的她,在擦边母婴赛道,成了孕妇纯欲第一人

都显怀还不能让你释怀的她,在擦边母婴赛道,成了孕妇纯欲第一人

生如稗草
2024-05-21 08:29:53
曼联大清洗!白菜价甩卖5年老臣,从此红魔不养庸才

曼联大清洗!白菜价甩卖5年老臣,从此红魔不养庸才

球事百科吖
2024-05-30 15:36:43
钱到账了,娃哈哈一线员工实发工资曝光

钱到账了,娃哈哈一线员工实发工资曝光

爱看剧的阿峰
2024-05-29 02:09:50
重庆一女硕士被黑人男友虐死,生前痛哭哀求:我要见见妈妈

重庆一女硕士被黑人男友虐死,生前痛哭哀求:我要见见妈妈

一场奇遇日记
2024-05-17 19:01:42
乌克兰持续摧毁俄军防空系统、雷达,瑞典紧急送来历史性大援助

乌克兰持续摧毁俄军防空系统、雷达,瑞典紧急送来历史性大援助

山河路口
2024-05-29 23:49:44
赖清德请求对话,大陆代表团抵台,不到24小时,解放军划下落弹区

赖清德请求对话,大陆代表团抵台,不到24小时,解放军划下落弹区

说天说地说实事
2024-05-29 12:54:46
转弯半径相差7倍,福建舰要3.4公里,里根号仅需500米

转弯半径相差7倍,福建舰要3.4公里,里根号仅需500米

三叔的装备空间
2024-05-29 20:48:35
天津女司机拒载病重乘客致其死亡,家属索赔60万,法院判了!

天津女司机拒载病重乘客致其死亡,家属索赔60万,法院判了!

大道微言
2024-05-30 00:03:52
江西漂亮女子被父母催婚,神情淡定无动于衷,一句话引发网友共鸣

江西漂亮女子被父母催婚,神情淡定无动于衷,一句话引发网友共鸣

雅清故事汇
2024-05-29 16:18:53
中国一则爆料疯传全网!父亲多年前4000枚比特币意外寻获 现价已破20亿元人民币

中国一则爆料疯传全网!父亲多年前4000枚比特币意外寻获 现价已破20亿元人民币

FX168链界观察
2024-05-29 12:42:11
突然续约!巴黎赢了!砸3亿转会费,挖意甲mvp+双子星,复仇皇马

突然续约!巴黎赢了!砸3亿转会费,挖意甲mvp+双子星,复仇皇马

阿泰希特
2024-05-30 11:15:50
从瑞典装甲车说起:照这个消耗速度,俄军会在两年内打光苏联遗产

从瑞典装甲车说起:照这个消耗速度,俄军会在两年内打光苏联遗产

鹰眼Defence
2024-05-30 11:15:29
中国女排主帅蔡斌摊牌:朱婷是否能首发出场,取决权不在于我

中国女排主帅蔡斌摊牌:朱婷是否能首发出场,取决权不在于我

体育快递小哥哥
2024-05-29 16:46:16
红星深度丨围观南京咖啡阿姨48小时,“这能火真是太抽象了”

红星深度丨围观南京咖啡阿姨48小时,“这能火真是太抽象了”

红星新闻
2024-05-29 18:48:24
主持人问韩红:想过要个孩子吗?韩红一脸真诚:我要过但郝蕾不给

主持人问韩红:想过要个孩子吗?韩红一脸真诚:我要过但郝蕾不给

回京历史梦
2024-05-30 11:02:40
400亿身价,9个娃,真是妥妥的人生赢家

400亿身价,9个娃,真是妥妥的人生赢家

壹点心语
2024-05-30 01:40:42
2024-05-30 17:52:49
墨谈科技
墨谈科技
业务数码玩家.无聊的博主
2911文章数 563关注度
往期回顾 全部

科技要闻

马斯克也给英伟达打工了

头条要闻

埃尔多安指责美欧是以色列的帮凶:你们手上沾满鲜血

头条要闻

埃尔多安指责美欧是以色列的帮凶:你们手上沾满鲜血

体育要闻

湖人队记再总结交易欧文失败三原因

娱乐要闻

法国这一夜,45岁章子怡惊艳世界!

财经要闻

卷成麻花的新茶饮:以价换量能突围吗?

汽车要闻

年内上市/纯电和增程可选 阿维塔07实车谍照曝光

态度原创

时尚
游戏
教育
房产
军事航空

不建议中年男人背的3种包包,听着洋气,实际土气,廉价又寒酸

《寂静岭2RE》主角新图曝光!明天有新预告公布

教育要闻

#清北毕业爸爸辅导孩子数学也抓狂 原来发呆不只是浪费时间

房产要闻

重磅!琼海出台楼市新政:住房出租、挂牌计划出售,都可减套数!

军事要闻

胡塞武装称又击落1架美军“死神”无人机 现场披露

无障碍浏览 进入关怀版