整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Angular9+Ant构建一个后台管理系统(三)

Angular9+Ant构建一个后台管理系统(三)

. 前言

上一节中我们学会了安装TypeScript支持,以及创建了一个基本的Angular工程。并尝试启动了工程,看到了首页。

本节内容中,我们要学会做我们的第一个页面,登录页面。

同时我们要学会集成我们使用的UI框架Ant Design For Angular,NG-ZORRO

2. 集成NG-ZORRO

2.1. NG-ZORRO简介

Ant Design :源自蚂蚁金服体验技术部的后台产品开发,蚂蚁金服的设计师和前端工程师经过大量的项目实践和总结,抽象出的一套企业级的交互视觉规范,统一后台项目的前端 UI 设计,屏蔽各种不必要的设计差异和前端实现成本,解放设计和前端开发资源。Ant Design提供了对Angular、Vue、React等前端框架的支持。

NG-ZORRO:是遵循 Ant Design 设计规范的 Angular UI 组件库,主要用于研发企业级中后台产品。全部代码开源并遵循 MIT 协议,任何企业、组织及个人均可免费使用。

官方网站可参考:https://ng.ant.design/docs/introduce/zh

2.2. NG-ZORRO安装

1、自动安装

只需要进入我们的工程目录,执行如下命令即可:

ng add ng-zorro-antd

VSCode中,步骤如下:

选择菜单栏中的终端(Terminal) - 新建终端(New Terminal),然后在新的终端窗口中输入上面的命令即可。

安装时会有选项提示,根据需要选择即可。

这样会自动安装成功NG-ZORRO。

我们可以启动工程看一下:

已经为我们配置了一个欢迎主页面,使用了侧边栏,而且侧边边栏是可以自动收缩的。

2、我们也可以手动安装NG-ZORRO

首先,在工程目录下,执行安装组件命令:

npm install ng-zorro-antd --save

接着,我们引用样式:

angular.json 中引入:

{
  "styles": [
    "node_modules/ng-zorro-antd/ng-zorro-antd.min.css"
  ]
}

style.css 中引入预构建样式文件:

@import "~ng-zorro-antd/ng-zorro-antd.min.css";

最后,我们想使用哪个组件模块,就在app.module.ts中引入就可以使用了。举个例子,我们要使用按钮组件,需要引入NzButtonModule:

import { NgModule } from '@angular/core';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    NzButtonModule
  ]
})
export class AppModule { }

然后在模板中使用:

<button nz-button nzType="primary">Primary</button>

3. 制作登录页面

3.1. 引入NG-ZORRO的Form表单组件

登录页面主要显示的都是表单,因此需要引入表单组件,在app.module.ts文件中增加如下部分代码:

import { NzFormModule } from 'ng-zorro-antd/form';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzInputModule } from 'ng-zorro-antd/input';
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    NzFormModule,
    NzButtonModule,
    NzInputModule,
    NzCheckboxModule
  ]
})
export class AppModule { }

上述代码中忽略了 既有的其他代码。我们只需要导入包:

import { NzFormModule } from 'ng-zorro-antd/form';
import { NzButtonModule } from 'ng-zorro-antd/button';
import { NzInputModule } from 'ng-zorro-antd/input';
import { NzCheckboxModule } from 'ng-zorro-antd/checkbox';

然后在@NgModule 的 imports属性中,增加NzFormModule、NzButtonModule、NzInputModule、 NzCheckboxModule即可。

3.2. 使用脚手架创建登录页面

切换到我们工程下的pages目录,完整路径:src/app/pages/。我们所有的页面都会放在这个目录下维护。

然后输入如下命令,创建login组件:

ng generate component login

全过程如下:

PS D:\ECMS\ecms-web\src\app\pages> ng generate component login
More than one module matches. Use skip-import option to skip importing the component into the closest module.
PS D:\ECMS\ecms-web\src\app\pages> ng generate component login --skip-import
CREATE src/app/pages/login/login.component.html (20 bytes)
CREATE src/app/pages/login/login.component.spec.ts (621 bytes)
CREATE src/app/pages/login/login.component.ts (271 bytes)
CREATE src/app/pages/login/login.component.css (0 bytes)
PS D:\ECMS\ecms-web\src\app\pages> 

第一次执行ng generate component login命令时提示More than one module matches,我们只需要加入--skip-import 参数即可。

生成的代码如下:

3.3. 创建登录表单

1、在login.component.html中加入如下代码:

<div style="text-align: center; margin: auto">
  <i class="fa fa-superpowers fa-4x" style="color: #40a9ff;"></i><!-- 这里放置LOGO -->
  <span class="align-middle" style="font-size:65px; color:grey;"> ECMS</span>
</div>
<div style="margin: 25px auto auto auto;">
  <form nz-form [formGroup]="validateForm" class="login-form" style="margin: auto;" (ngSubmit)="submitForm()">
    <nz-form-item>
      <nz-form-control nzErrorTip="请输入登录用户名!">
        <nz-input-group nzPrefixIcon="user">
          <input type="text" nz-input formControlName="userName" placeholder="用户名/手机/邮箱" />
        </nz-input-group>
      </nz-form-control>
    </nz-form-item>
    <nz-form-item>
      <nz-form-control nzErrorTip="请输入登录密码!">
        <nz-input-group nzPrefixIcon="lock">
          <input type="password" nz-input formControlName="password" placeholder="密码" />
        </nz-input-group>
      </nz-form-control>
    </nz-form-item>
    <div nz-row class="login-form-margin">
      <div nz-col [nzSpan]="12">
        <label nz-checkbox formControlName="remember">
          <span>记住</span>
        </label>
      </div>
      <div nz-col [nzSpan]="12">
        <a class="login-form-forgot">忘记密码?</a>
      </div>
    </div>
    <button nz-button class="login-form-button login-form-margin" [nzType]="'primary'">登录</button>
    或者 <a> 去注册! </a>
  </form>
</div>

2、在login.component.css中加入如下代码:

.login-form {
  max-width: 300px;
}

.login-form-margin {
  margin-bottom: 16px;
}

.login-form-forgot {
  float: right;
}

.login-form-button {
  width: 100%;c
}

3、在login.component.ts中加入如下代码:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';  // 导入构建表单需要的相关组件
import { Router } from '@angular/router'; // 导入Router组件

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {

  validateForm!: FormGroup; // 定义表单组

  constructor(private fb: FormBuilder,
             private router: Router) { } // 注入FormBuilder对象 和Router对象 

  ngOnInit(): void {
    //  构建表单对象
    this.validateForm=this.fb.group({
      userName: [null, [Validators.required]],
      password: [null, [Validators.required]],
      remember: [true]
    });
  }

  // 表单提交
  submitForm(): void {
    for (const i in this.validateForm.controls) {
      this.validateForm.controls[i].markAsDirty();
      this.validateForm.controls[i].updateValueAndValidity();
    }
    // 表单验证失败返回
    if (this.validateForm.invalid) {
      return;
    }

    // 表单验证通过,调用登录逻辑
    // 登录代码忽略
    // 登录成功跳转到welcome 页面
    this.router.navigate(['welcome']);
  }
}

4. 配置路由

我们修改路由把登录页面设置为默认加载页面:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginComponent } from './pages/login/login.component';
import { WelcomeComponent } from './pages/welcome/welcome.component';

const routes: Routes=[
  { path: '', pathMatch: 'full', redirectTo: 'login' }, // 当前网站根
  { path: 'login', component: LoginComponent, data: { title: '登录' } },
  { path: 'welcome', component: WelcomeComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

5. 导入LoginComponent组件

我们修改app.module.ts文件,添加如下的组件引用:

import { LoginComponent } from './pages/login/login.component';
import { WelcomeComponent } from './pages/welcome/welcome.component';

@NgModule({
  declarations: [
    AppComponent
    , LoginComponent
    , WelcomeComponent
  ],
  imports: [
   
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

代码中我忽略了不相干的代码。

6. 启动

我们启动工程来看一下效果:

直接点击登录看一下:

我们随便输入一个用户名和密码,点击登录看看:

成功地跳转到了welcome页面。

7. 小结

本篇教程中我们学习了如何集成NG-ZORRO到Angular工程中,然后我们尝试着,使用NG-ZORRO的表单组件,构建了一个登录页面。并配置了网站的默认页面为登录页面。大家可以看到 使用Angular + NG-ZORRO构建一个前端的网站是如此简单。

没上手 OPPO Find N 之前,笔者对折叠屏并无太大兴趣,一方面,笔者更看重手机的实用性,折叠屏虽然有更明显的大屏优势,但过万的售价,以及折痕、应用适配等一系列问题,随便挑一点就足以“绝杀”;另一方面,则是在 OPPO Find N 之前,笔者已经陆续上手过其他折叠屏手机,对折叠屏的新鲜感早已褪去。

那么为什么 OPPO Find N 的发布却让笔者兴奋了很久?同样来自两个方面的原因:

其一,OPPO Find N 在形态方面有了很大的改进,特别是外屏不再是夸张的瘦长以及主打的“隐痕”,非常值得体验一番;

其二,Find N 7699 元的起售价听起来相当的诱人,几乎与一台 Pro 版本的 iPhone 相当,这也意味着折叠屏手机定价至少不再“高不可攀”。

在 OPPO Find N 发布之后,笔者便选择将 OPPO Find N 作为主力机使用至今,那么这一段时间来,OPPO Find N 都带来了哪些不一样的体验感受?又解决了哪些折叠屏手机中存在的问题?

本篇文章,IT之家将围绕 OPPO Find N 的大小屏、折叠形态、应用交互、游戏体验等方面深入体验,详细和大家分享一下 OPPO Find N 的用机感受。

第一部分:外观设计

OPPO Find N 依旧延续了 OPPO 产品惯有的精致感,中框采用了抛光金属设计,看起来很有一种莹润、精致的质感。

铰链外露的部分做了抛光加凹陷喷砂搭配的设计,在凹陷区域,还印有“DESIGNED FOR FIND”的文字,高级感一下就上来了。

手机的外屏、背板均采用 3D 微曲面设计,保证显示画面视觉平衡的同时,也更加贴合手掌。

再看手机的背面,延续了 Find 系列“流体曲线”的设计语言,影像模组还是环形山曲面设计,可惜并没有采用 Find X3 系列的一体化曲面,因此视觉和触觉上,是存在一定割裂感的。

OPPO Find N 背板部分顶部有一枚麦克风,侧边是指纹识别电源二合一按键,底部是扬声器、USB Type-C 接口和麦克风。不过,折叠状态下,音量键和指纹键过于靠近,很容易误触

OPPO Find N 采用了双 box 立体声双扬声器,支持杜比全景声,出色的音质表现是毋庸置疑。不过这两枚扬声器均位于机身底部,因此在使用过程中,声音仍是来自一个方向,这一点有些吃亏。

OPPO Find N 内置的 X 轴线性马达,OPPO 调教的非常出色,包括后台清理、指纹解锁等等场景下,以及键盘输入(仿真键盘)的震动反馈,都非常的细腻真实,可以说是安卓阵营第一梯队了,必须好评。

折叠状态下,OPPO Find N 的三围尺寸分别是 132.6mm、73mm、15.9mm,重量为 275g,不看厚度和重量,妥妥的小屏机。275g 重量在折叠屏手机中也属于很轻的了,不过,因为 OPPO Find N 尺寸小,握持时重量会集中在手掌中,所以会产生较为明显的坠手感。

当然,展开之后上述问题都会解决,大屏会将这部分重量和厚度均匀出去,所以双手握持就非常舒适了。

第二部分:大小屏体验

不同于之前的折叠屏手机折叠后的“遥控器”形态,当 OPPO Find N 合上时,5.49 英寸、18:9 的屏幕让它看起来就像一款正常的传统小屏手机,单手就可以握持掌控。不过,在折叠状态下,OPPO Find N 是存在一定的机身厚度的,更像是两台 iPhone12 mini 叠加在一起,所以,在各种角度下看折叠状态下的 OPPO Find N,都有种“萌胖”的感觉。

将 OPPO Find N 展开后,就成了屏幕 7.1 英寸的小平板,8.4:9 的比例在观感上像是一块正方形。此外,OPPO Find N 在展开状态下,打开应用就可以直接使用,而不是像其它折叠屏手机那样,需要先旋转一下角度。

这块 AMOLED 柔性内屏采用了三星 E5 材质,支持 LTPO,支持 1-120Hz 自适应刷新率,内屏展开之后能够带来尤为震撼的视觉冲击力。

外屏方面,OPPO Find N 同样采用了 AMOLED 柔性屏,同样支持 100% P3 色域,1972 × 988 的分辨率和 60Hz 刷新率可以满足日常使用。不过,当你从外屏切换至内屏、从内屏切换至外屏时,在体验上会稍显割裂感。

即便如此,笔者认为 OPPO Find N 的这块外屏仍是可圈可点的,其最大的优势并不是在参数规格,而是在于形态方面 ——

部分折叠屏手机的外屏都采用了非常夸张的显示比例,折叠状态下握在手中像是拿着一台遥控器,夸张的显示比例甚至还会出现画面裁切等问题(比如刷抖音时,画面两侧会有切割),严重影响体验。相比之下,OPPO Find N 外屏的优势非常明显,18:9 的显示比例就是一块再正常不过的全面屏,应用无需额外的优化适配,如果你愿意,完全可以当作主屏全天候使用

OPPO Find N 还给出了大小屏接力功能 。

折叠屏手机内屏转外屏使用过程中,存在一个交互逻辑,比如我把折叠屏合上,此时手机并不知道我是否要继续使用外屏,很多折叠屏给出的方案是,内屏合上了,外屏自动点亮,如果我不想用了,还需要再按一下电源键才能放回口袋。

OPPO Find N 的大小屏接力,内屏折叠之后,小屏会出现上滑提示,上滑继续内屏的内容浏览,应用衔接更是做得非常流畅;你也可以直接放进口袋(3 秒无操作自动息屏),这种交互逻辑显然要更人性化一些。

(大小屏接力 GIF 演示)

第三部分:折叠、折叠、折叠

折痕是折叠屏手机目前存在最大的问题之一,准确的讲,OPPO Find N 并没有消灭折痕,而是将“折痕问题”给淡化了,它不会让你在使用手机的过程中因为屏幕中央的折痕分分钟“出戏”,事实上笔者在使用 OPPO Find N 的这段时间,“折痕”真的可以忽略不计,展开后屏幕一体感更强,也让笔者更愿意在展开状态下使用 Find N。

和此前的折叠屏手机相比,OPPO Find N 采用了“用折痕面积换折痕深度”的思路,内屏是以“水滴”的形状折叠,折痕区域的面积比较大,但折痕非常浅,息屏状态下,只有在不同角度的光线下才能感受到,或者是用指甲盖在内屏中央滑动,才感受到屏幕是不平整的。日常使用过程中,我想没有几个折叠屏用户会在意这些细节。

如果有人非盯着折痕问题不放,那显然也不是折叠屏手机的潜在用户了,举个不恰当的例子,了解三缸机的用户远比买过三缸机的用户更在意抖动问题。

OPPO Find N 所实现的“微痕”,跟 OPPO“水滴铰链”有很大关系,配合 OPPO 的研发调校,最终实现了几乎无折痕。

当 OPPO Find N 折叠屏合上后,屏幕四边的贴合很紧密,因此不用担心日常使用会钻进沙子灰尘等划伤屏幕。同时 UTG 使得内屏硬度更高,对一些有美甲的女性用户比较友好。

根据 OPPO 介绍,Find N 经过莱茵 20W + 折叠无忧认证,哪怕每天折叠 100 次,寿命也可以坚持超过 5 年。笔者使用 OPPO Find N 的这段时间来,平均每天折叠次数达到了百次 +,但现在看来,仍是没有任何问题的。

OPPO Find N 的“水滴铰链”还实现了不错的悬停功能。即便是在日常使用中悬停功能我用的并不是很多,但个人还是要吹一波:

它实现了手机在折叠、展开之外的第三种使用形态“悬停交互”给折叠屏手机留下了很大的想象空间,比如游戏开发者完全可以借助 OPPO Find N 的折叠优势和硬件形态,开发出类似任天堂 3DS 游戏机这样的操作和玩法体验。

(悬停交互 GIF 演示)

OPPO Find N 支持 50° 到 120° 任意角度的自由悬停,并且带来了悬停摄影、悬停观影、悬停视频通话、悬停会议等等功能。

以相机悬停为例,拍摄一些长曝光样张,或者是延时摄影,往往需要配合三脚架,而在悬停模式下,OPPO Find N 下半部分就可以作为“三脚架”固定在平面上。

(悬停摄影 GIF 演示)

再比如悬停观影,将屏幕调整至任意角度放在桌面,就可以一半屏幕播放影片,一半屏幕进行操控。

(悬停观影 GIF 演示)

悬停视频通话,把手机“立”在桌面,就能解放双手,一边通话一边做别的事了。悬停视频通话目前支持 QQ,开启后,上屏通话界面五五开左右分布画面,下屏显示控制按钮,双方都看得清对方。

(悬停视频通话 GIF 演示)

可见,OPPO Find N 不仅在折叠屏的硬件品质上做了创新与打磨,更没有浪费折叠屏的天然优势,挖掘了很多与折叠相关的细节功能。

第四部分:应用交互体验

折叠屏在展开状态下,严格意义上讲就是一台安卓平板,因此折叠屏好不好用,很大程度上在于大屏应用的适配和交互优化上,这也非常考验折叠屏厂商的软实力。

应用体验部分,首先要单独讲一下微信。

在 OPPO Find N 等折叠屏手机中,微信是可以以平板模式登录的,跟手机上登录的微信不冲突,也就是说可以同时登录手机微信和折叠屏微信(平板),这对于双机党用户来说,无疑是一个意外的惊喜。

据笔者观察,很多折叠屏用户都是双机党,有一台直屏机作为主力机或备用,两台设备同时登录微信,省去了来回登录微信的繁琐(每次都要登录密码,聊天记录还不同步),这简直是微信最良心的功能了。

在大屏状态下,OPPO 还优化了输入法使用体验。比如输入法布局上,OPPO 设计了分离式键盘,同时还精密测量了上百位用户握持姿势,对输入区域进行了优化,让打字体验更自然、舒适。

(输入法 GIF 演示)

再讲一下观影体验。

客观来讲,OPPO Find N 在诸如观影、游戏以及部分应用等场景下,相较于传统直板机,并没太明显的大屏优势,比如现如今 21:9 的电影根本无法铺满 OPPO Find N 这块接近 1:1 的 7.1 英寸内屏,上下的黑边会造成屏幕空间的极大浪费,电影显示面积甚至还没有传统的手机大。这也是目前所有折叠屏手机都存在的“问题”。

(21:9 电影,Find N 显示面积比传统 6.5 英寸直板手机要小一些)

看到这里你或许会吐槽,折叠屏既然有大屏却无法充分利用,那买折叠屏图啥?事实上这也是笔者刚接触折叠屏时产生的疑惑。不过在长时间体验 OPPO Find N 之后,上述观点已经有了改变。

首先,21:9 的电影对 OPPO Find N 确实并不友好(但几十年前的老电影非常友好,比如猫和老鼠,银幕比例 4:3,画面基本就能全部铺满),这是客观存在的问题,需要每一位对折叠屏手机有购买意向的用户都知晓。但是,在现代电影之外,诸如哔哩哔哩等视频平台,视频、直播大多都是以 16:9 的比例呈现,在 16:9 的比例下,虽然画面仍不能填满 OPPO Find N,但画面显示面积事实上是要比传统的直板手机更大一些的。

(16:9 视频画面,Find N 显示面积比传统 6.5 英寸直板手机更大)

其次,OPPO Find N 观影时的上下黑边,刚好给弹幕留下了显示空间,不会遮挡画面。

(无论是优酷视频还是B站,弹幕都尽可能的显示在上黑边区域)

OPPO Find N 的大屏优势,更适合在文字阅读、图片浏览等应用场景使用,比如微信阅读,大量的文字内容可以全部铺满屏幕,用 OPPO Find N 看小说、看漫画,简直就是神器。

再比如刷微信朋友圈、公众号文章、刷微博、论坛等等,更大的配图带来了更强的视觉冲击力,朋友圈图片更是点击就直接铺满屏幕,无需双击屏幕放大。

(不同应用场景下的大屏体验)

买来折叠屏只用来看图?文字?岂不是有点浪费?如何进一步放大 OPPO Find N 的大屏优势呢?这就需要 OPPO 的软实力了。OPPO Find N 在系统设置内,专门加入了一个“大屏专区”,诸如自由浮窗、应用分屏、悬停模式、兼容模式、平行视窗... 与大屏有关的所有设置和功能,都能在“大屏专区”内可以找到。

应用分屏体验

首先是应用分屏,要想折叠屏手机用的爽,这个功能必不可少。

应用分屏,简单理解就是 OPPO Find N 内屏分为两半,可以同时打开两个 App 使用(一台手机当两台用)。OPPO Find N 给出的分屏方法也相当的简单,在 App 展开的情况下,双指在屏幕中间从上往下“一划”,就直接分屏了,交互非常直接。

(应用分屏 GIF 演示)

分屏状态下,不同应用间图片、文字、文件,可以自由拖拽,比如看新闻的时候想记录笔记,就可以轻松将新闻的段落拖拽到便签中。再比如一边微信聊天一边逛淘宝等等。

左右拖动屏幕中央的三个小点,还能让两款分屏应用获得不同的分屏面积,非常贴心。

如果你经常使用某两款应用分屏,还可以将这个分屏组合保存在桌面,下次点击一下就能直接用这两个应用进行分屏,这就更加高效了。

一个大屏同时显示两个应用,大屏优势这不就体现出来了?

不过,在分屏状态下,退出其中的一款应用之后,OPPO Find N 就立马结束了分屏状态,此时另外一款应用就直接拉伸铺满了整个屏幕,想要再分屏另外一个应用就得重新操作一番,这一点笔者不是很理解。

自由浮窗

OPPO Find N 的大屏,给了“自由浮窗”更大的使用空间,而 OPPO Find N 呼出小窗的方法也是非常简单,全屏状态下,屏内四指收缩,即可迅速调出小窗模式。

(自由浮窗手势操作演示)

平行视窗

这个功能类似华为的平行视界,简单理解就是一个应用,两屏显示。比如当你在横屏状态下逛淘宝的时候,你可以用屏幕的一边去和客服聊天,另一边则用来逛新店;再比如你在聊微信的时候,你可以一边刷朋友圈,一边和朋友畅聊等等。

(淘宝)

(美团)

(哔哩哔哩)

(微信)

不同应用的平行视窗截图

这也是传统直板手机所不具备的优势。

IT之家咨询 OPPO 客服了解到,目前 OPPO Find N 平行视窗支持钉钉、微信、QQ 邮箱、淘宝等 App,不算多,但也基本能够满足需求。

另外强调一点,IT之家的“平行视窗”也已经在路上了

兼容模式

一些应用未做好全屏显示优化,或不支持平行视窗(或关闭平行视窗),此时打开应用之后,虽然画面铺满了 OPPO Find N 整个屏幕,但画面也是局部放大,显示内容甚至比不过传统手机。

另外有些应用,打开之后图片和文字的排版会稍显不协调。

(上面截图可以看到,在全屏模式下,图片多的 App 显示内容明显比不过正常比例的手机)

OPPO Find N 提供了“兼容模式”,你可以自行选择应用显示比例,包括全屏、4:3 和 16:9。

这里以《网易云音乐》为例,全屏状态下,《网易云音乐》顶部的 Banner 图就占了屏幕的一半显示面积,图是看爽了,但下方的内容也被遮挡了很多。选择 16:9,虽然两侧有白边,但此时《网易云音乐》已经正常显示,点击两侧的箭头,你还可以自由选择《网易云音乐》的显示位置。

当然,以笔者的实际体验来说,绝大部分应用的全屏体验都是不错的,OPPO 的“兼容模式”,是给了用户多一个选择。

游戏体验

从“全屏应用”延伸到游戏。在《王者荣耀》《原神》等游戏中,OPPO Find N 的大屏是不占优势的,虽然中心画面会进行放大,但游戏画面两侧实际上是被裁切的,你同样可以在“兼容模式”中设置 4:3 或 16:9 显示比例。

像《王者荣耀》这样对视野有严格要求的 MOBA 游戏,用全屏玩是明显吃亏的。

不过,《和平精英》是个例外,在全屏模式下,和平精英并不是局部放大裁切,而是像超广角一样,有了更大的显示视野,比如下图,16:9 和全屏显示模式下,全屏显然显示的画面更广阔。

(和平精英全屏后,画面视野明显增大)

《原神》在全屏显示比例下,画面虽然也是裁切放大,但好处是放大之后画面细节更丰富了,人物的动作细节也进一步放大。如果你想即保留一定的视野范围,也获得更丰富的画面细节,可以尝试一下 4:3 显示比例。

(原神全屏后,视野虽然缩小,但画面细节更丰富)

总而言之,“兼容模式”给了 OPPO Find N 用户不同的选择,用一种另类的方式,弥补了“大屏无法充分利用”的这个遗憾点。

第五部分:硬件体验

OPPO Find N 折叠屏手机搭载的是目前的旗舰骁龙 888 移动平台,有 8GB +256GB,12GB+512GB 两个内存和存储选项。IT之家拿到的是 12GB+512GB ,核心配置方面是旗舰水准,没什么好说的。

关于性能部分,可以查看IT之家微信公众号的评测文章:

《用了 OPPO Find N,才知道什么叫最好用的折叠屏》

充电续航

续航额外提一笔。OPPO Find N 搭载了 4500mAh 的电池,对于这样小尺寸的折叠屏手机来说,很不容易。

IT之家也进行了简单的测试,OPPO Find N 满电的情况下,大屏状态,先在 Wi-Fi 网络下玩了 30 分钟的《王者荣耀》游戏,耗电 6%。接着又在 Wi-Fi 网络下用《哔哩哔哩》看了 40 分钟的 1080P 高码率电影,耗电 3%。根据两项测试结果,再结合日常使用、待机的体验,OPPO Find N 的续航能力大大至少是超过笔者预期的。

在日常使用中,OPPO Find N 的续航是足够满足笔者一天正常使用的(基本全程使用大屏,早晨 8 点到晚上 6 点期间无需充电)。

通过下面不同时间、不同应用场景的耗电截图,基本可以了解到 OPPO Find N 的续航水平。

(笔者日常使用中的电量截图)

至于 33W 的快充,肯定是不尽兴的。在电量为 0 的情况下,30 分钟可充到 60%,56 分钟充满到 100%,这个成绩放在 2022 年,只能说中规中矩吧。

(OPPO Find N 充电时间表)

影像体验

相机方面,OPPO Find N 有后置三摄系统,包括 50MP 广角主摄,IMX766 传感器、16MP 超广角镜头、13MP 2X 长焦镜头。

OPPO Find N 的主摄是响当当的旗舰水准,毕竟早在一年前 OPPO 就首发了 IMX766,在接下来的 OPPO Find X3 系列上,这枚 IMX766 也被调教的极其出色,所以 OPPO Find N 的主摄影像实力,没什么好担心的。

体验部分,OPPO Find N 借助大屏的优势,可以实现照片的“即拍即预览”功能,如下图所示,右侧屏幕拍摄,随后样张在左屏展示。

此外,给女朋友拍照时,你还可以打开“小屏预览”,女朋友也可以通过外屏查看拍摄状态等。

样张部分,主摄照片曝光充足,色彩明艳,整体很讨好眼球。

放大之后,大屏上这么小的文字都能看清,可见细节解析力也是很猛的。

换一个光线对比更强烈的场景,下面这张照片更能看出,OPPO Find N 对色彩的呈现的确很明艳讨喜。

而且,尽管是迎着夕阳,背光的电梯、花束依然亮度充足,细节丰富,远处的楼房也没过曝,动态范围表现很好,画面看起来很通透。

接着是夜拍表现,下面这张照片实拍环境是比较黑暗的,但 OPPO Find N 的直出照片呈现出不错的亮度,而且画面中只有小屋上的白布高光处出现了一些过曝,整体来说,宽容度表现很好。

使用夜景模式再拍一张,画面整体明亮了一些,小屋上的白布高光处也被压了下来,动态范围更上一层楼。

下面再为大家展示一些来自 OPPO Find N 的拍照样张,供大家参考:

(超广角)

(主摄)

(2X)

(主摄)

(主摄)

(主摄)

(主摄夜景)

(主摄夜景)

“从尝鲜,到常用”

在笔者撰写这篇文章的时候,OPPO Find N 的全网预约量已经突破 100 万,“从尝鲜,到常用”,单从上述数据来看,OPPO Find N 是有资格喊出的这句口号的。

作为 OPPO 的首款折叠屏产品,Find N 的完成度非常高的,在这几年时间里,OPPO 没有跟风强上折叠品手机,而是耐心打磨体验,从尺寸形态到转轴、折痕,从应用交互的实用性再到悬停的创新体验,Find N 的每一处细节,都隐藏着 OPPO 多年来对折叠屏手机的观察和思考。更何况,7699 元起的售价,OPPO Find N 注定将成为折叠屏手机普及道路上的一座里程碑。

最后,OPPO Find N 适合哪些用户?

第一,预算够多,对折叠屏手机非常感兴趣,OPPO Find N 作为日常的主力机使用是毫无问题。

第二,有直板机作为备用机,想买一台折叠屏尝鲜的用户,OPPO Find N,将会是你体验折叠屏最好的选择。

推荐阅读:

《【IT之家开箱】OPPO Find N 折叠旗舰图赏:无缝折叠,自由悬停》

《终于有一款好看又实用的折叠屏手机了!》

我是从今年5月份第一次接触流马这个平台。第一次听到这个名字的时候,就觉得挺有趣的,猜测其名字应该是取自诸葛亮的“木牛流马”,后来和作者证实了一下,确实如此。当初诸葛亮发明木牛流马是为了提高运输效率,而流马测试平台是为了提高测试效率,可以说这个名字取得“恰到好处”。

本文一万两千字左右,我写了好多天,可能是我耗时最久的一篇文章。其实写文章不是最难的,难的是边学习、边摸索、边踩坑、边解决问题、边写文章记录、边总结。所以写得还算是比较用心的,整体来说也比较详细。读起来可能会有点长,大家可以先关注收藏、后期有时间、空下来了再照着文章内容仔细研究。内容大致分为以下四个部分:

简介篇

  • 项目概述:技术栈、工作原理
  • 项目功能简介:功能特点

部署篇

  • 部署规划
  • 依赖环境部署(JDK、MySQ、NGINX、Git、NodeJS、Python3)
  • 代码打包:克隆项目、前端代码打包、后端代码打包
  • 项目部署:前端部署、后端部署、执行引擎部署

使用篇

  • 接口测试:创建接口(添加引用公共参数、添加引用自定义参数)、测试用例(参数关联)、业务流程测试实践
  • web自动化测试:元素管理(添加元素)、测试用例(添加元素)、设计测试场景
  • 测试计划、测试集合与测试用例相互之间的关系

总结篇

  • 使用总结:常见的使用注意事项,如变量引用、函数引用、关联参数引用等
  • 优化建议:结合真实使用过程,从用户角度出发,提出的7条优化建议
  • 优缺点总结:优点、缺点、评分(从不同角度评测打分)

【简介篇】

以下项目概述及功能介绍内容来自官网及GitHub项目介绍

一、项目概述

流马是一款低代码自动化测试平台,旨在采用最简单的架构统一支持API/WebUI/AppUI的自动化测试。平台采用低代码设计模式,将传统测试脚本以配置化实现,从而让代码能力稍弱的用户快速上手自动化测试。同时平台也支持通过简单的代码编写实现自定义组件,使用户可以灵活实现自己的需求。

项目分为平台端和引擎端,采用分布式执行设计,可以将测试执行的节点(即引擎)注册在任意环境的任意一台机器上,从而突破资源及网络限制。同时,通过将引擎启动在本地PC上,方便用户快速调试测试用例,实时查看执行过程,带来传统脚本编写一致的便捷。

官网:http://www.liumatest.cn/

代码地址:https://github.com/Chras-fu/Liuma-platform

部署文档:https://docs.qq.com/doc/p/c989fa8bf467eca1a1e0fa59b32ceab017407168

使用手册:https://docs.qq.com/doc/p/1e36932d41b40df896c1627a004068df9a28fc3f

平台技术栈:前端VUE+ElementUI,后台Java+SpringBoot,测试引擎Python。

二、功能介绍

1.API测试

  1. 支持单接口测试和链路测试。
  2. 支持接口统一管理,支持swagger导入。
  3. 支持一键生成字段校验的接口健壮性用例。
  4. 支持全局变量、关联、断言、内置函数、自定义函数。
  5. 支持前后置脚本、失败继续、超时时间、等待/条件/循环等逻辑控制器。
  6. 支持环境与用例解耦,多种方式匹配域名,让一套用例可以在多个环境上执行。

2.WebUI测试

  1. 支持关键字驱动,零代码编写用例。
  2. 支持UI元素统一管理,Excel模板批量导入。
  3. 支持自定义关键字,封装公共的操作步骤,提升用例可读性。
  4. 支持本地引擎执行,实时查看执行过程。
  5. 支持与API用例在同一用例集合顺序执行。

3.AppUI测试(1.1版本上线)

  1. 支持WebUI同等用例编写和执行能力
  2. 支持安卓和苹果系统
  3. 支持持真机管理、投屏和在线操作
  4. 支持控件元素在线获取,一键保存元素
  5. 支持实时查看执行过程

【部署篇】

一、部署说明

1.部署说明

官方部署文档地址:https://docs.qq.com/doc/p/c989fa8bf467eca1a1e0fa59b32ceab017407168,共提供了两种部署方式,一种是容器部署,一种是常规部署。容器部署的好处是简单、快捷,常规部署方式的好处是相对于容器来说、出现问题容易排查,缺点是步骤较为繁琐。两种方式各有优劣,根据自己的喜好自由选择即可。本文采用的是常规部署方式。

2.部署规划

机器/系统

部署环境

说明

192.168.1.123,CentOS7

JDK8

MySQL8

Nginx

CentOS7内网服务器:

  • 用于运行后台Java服务+前端
  • Nginx用于代理转发
  • MySQL为后台存储数据库

192.168.1.131,Windows10

Git

JDK8

Maven

IDEA编辑器

NodeJS

个人Windows10办公电脑:

  • Git用于克隆前后台以及引擎代码代码到本地
  • IDEA编辑器用于修改配置文件
  • Maven自动下载依赖包、打包程序
  • NodeJS编译打包前端程序

192.168.1.188,Windows7

Python3

Selenium

Chrome

ChromeDriver

同一内网下的其他Windows主机:

  • Python3为执行引擎环境
  • Selenium为Web自动化测试工具
  • Chrome谷歌浏览器
  • ChromeDriver谷歌浏览器驱动程序

关于执行引擎机,也可以继续使用个人办公电脑作为执行引擎机,考虑到个人电脑经常会关机重启,就需要来回启动执行引擎,比较麻烦,所以我就选了一台本地Windows主机。当然也可以部署在Linux系统上,不过对于UI自动化测试而言,没有可视化的界面展示,调试起来相对麻烦一些。

二、依赖环境部署

1.安装Java1.8

CentOS服务器和个人Windows电脑分别需要安装JDK。CentOS下,推荐脚本部署方式:

安装脚本下载:https://share.weiyun.com/6JMLvSyK

JDK包下载地址:https://share.weiyun.com/mKDxXd1x

source jdk_install.sh  # 通过source命令安装,省去配置环境变量步骤

2.安装mysql

1)安装mysql

CentOS下安装,本次通过docker进行快速安装,如服务器或其他内网机器已安装mysql,直连即可,可以忽略此步。注意要使用8.0+版本的mysql,我用的是5.7.33版本,启动时候就会报错不支持。

docker run -d --restart always --name mysql -e MYSQL_ROOT_PASSWORD=123456 -p 3307:3306 mysql:8.0.28

2)登录mysql

进入mysql容器

docker exec -it mymysql sh

连接mysql

mysql -uroot -p  # 登录mysql,根据提示输入密码123456

2)创建数据库

进入mysql命令行执行:

mysql> create database liuma character set utf8 collate utf8_general_ci;

3.安装nginx

CentOS下安装,推荐脚本部署方式

nginx安装脚本下载地址:https://share.weiyun.com/HLuVRTO2

nginx安装包下载地址:https://share.weiyun.com/uhffdijl

将其下载下来,上传到服务器,执行以下命令安装:

source nginx_install.sh

4.安装git

Windows下安装,用于拉取项目代码,下载后双击、按照提示一步步安装。

下载地址:https://share.weiyun.com/NJBlZGmE

5.安装node.js

Windows下安装,用于安装前端依赖、打包编译。

下载地址:https://share.weiyun.com/2PpWyXkz,下载下来后双击安装即可。

更换淘宝镜像源

1.临时更换

npm --registry https://registry.npm.taobao.org install node-sass(要安装的模块)

2.永久更换

npm config set registry https://registry.npm.taobao.org
npm config get registry  # 查看是否更换成功

3.通过cnpm使用

npm install -g cnpm --registry=https://registry.npm.taobao.org

6.安装python3

CentOS或Windows下安装均可,执行机选用哪个系统就安装在哪个系统下。如果是Linux系统,可以参考之前的文章《Linux下一键安装Python3&更改镜像源&虚拟环境管理技巧》,如果是Windows系统,则在Windows系统下安装python3.

三、代码打包

1.克隆项目代码

git clone https://github.com/Chras-fu/Liuma-platform.git  # 克隆平台代码
git clone https://github.com/Chras-fu/Liuma-engine.git  # 克隆引擎代码

平台代码目录:

  • LiuMa-backend:后台代码
  • LiuMa-frontent:前端代码

2.打包前端代码

进入前端文件目录,安装相关依赖并执行构建

npm install  # 安装相关依赖
npm run build  # 构建

出现"Build complete."提示代表构建成功:

构建成功后,目录下会生成dist文件目录,可以将其打包成.zip格式并上传至服务器,然后再解压

3.打包后端代码

1)安装依赖包

用IDEA打开liuma-platform/LiuMa-backend,使用maven安装依赖

2)修改配置

① 数据库配置

文件位置:liuma-platform/LiuMa-backend/src/main/resources/application.properties,配置如下所示:

  • username:数据库用户名;
  • password:数据库密码;
  • url:连接数据库的URL地址;
# database
spring.datasource.password=123456
spring.datasource.username=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3307/liuma?serverTimezone=UTC&characterEncoding=utf-8

注意事项:

  • 项目部署的服务器与数据库处于同一主机时可使用127.0.0.1,如不在同一主机下,需改为该主机的IP地址;
  • 3307为前面docker部署mysql时映射的端口号,按照你自己的数据库端口号配置即可;

② 邮件配置

文件位置:liuma-platform/LiuMa-backend/src/main/resources/application.properties,配置如下所示:

# aliyun 阿里云
# 阿里云邮件key
aliyun.email.accessKey=LTAI5tDVn8kT1avi84cFX8TT
# 阿里云邮件secret
aliyun.email.accessSecret=Dq8pm0DkZSqeMwRKOQhEid3fGPkL09
# 发送人邮箱地址
aliyun.email.runnerSenderAddress=jigang.chen@1897745962796526.onaliyun.com
aliyun.email.runnerSenderName=执行通知机器人

③ 七牛云配置

文件位置:liuma-platform/LiuMa-backend/src/main/resources/application.properties,配置如下所示:

# qiniuyun 七牛云
# 七牛云ak
qiniu.cloud.ak=15252162668
# 七牛云sk
qiniu.cloud.sk=Jigang.chen520
# 七牛云空间名
qiniu.cloud.bucket=chenjigang-test
# 七牛云加速域名
qiniu.cloud.downloadUrl=rcc3794ta.hd-bkt.clouddn.com
qiniu.cloud.uploadUrl=http://upload-cn-east-2.qiniup.com

3)maven打包

提示“BUILD SUCCESS”即表示打包成功,目录下会多出一个LiuMa-1.0.3.jar的jar包(我目前拉的最新代码,打包出来的是1.0.3,还有个LiuMa-1.0.0.jar包是两个月前打包的)

四、项目部署

1.平台部署

1)上传打包后的前端文件

将前端打包后的文件夹dist上传到:nginx安装目录/usr/local/nginx/html/下

2)上传打包后的后端文件

可以在/home目录下新建一个文件夹liuma,用于存放前面打包的jar包文件:LiuMa-1.0.3.jar,执行命令,后台启动服务:

nohup java -jar LiuMa-1.0.3.jar > logs.log 2>&1 &

启动后,可以查看logs.log日志文件,看看是否启动成功,以及是否成功连接到数据库,连接成功后自动创建相关数据表:

3)配置Nginx

① 新建nginx_liuma.conf

在nginx的/usr/local/nginx/conf目录下新建nginx_liuma.conf,nginx用于配置server的代理转发,详细配置如下:

#user  nobody;
worker_processes  1;

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 8888;
        server_name 192.168.1.122;
        location / {
            index index.html index.htm;
            root /usr/local/nginx/html/dist;
        }

        location /autotest {
            proxy_pass http://127.0.0.1:8080;
            proxy_http_version 1.1;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Origin "";
        }

        location /openapi {
            proxy_pass http://127.0.0.1:8080;
            proxy_http_version 1.1;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Origin "";
        }

        access_log /usr/local/nginx/html/wwwlogs/access.log;
    }
}

② 测试配置

nginx -t -c /usr/local/nginx/conf/nginx_liuma.conf

测试过程中可能会出现失败提示"nginx: [emerg] open() "/usr/local/nginx/html/wwwlogs/access.log" failed (2: No such file or directory)",原因是html目录下没有wwwlogs/access.log这个文件路径,直接新建一个wwwlogs目录和access.log文件即可。

③ 指定配置文件启动nginx

nginx -c /usr/local/nginx/conf/nginx_liuma.conf

4)验证部署情况

访问前端:http://192.168.1.122:8888/,管理员账号:LMadmin,密码:Liuma@123456

登录后的页面如下所示:

5)问题排查

因为流马是前后端分离项目,所以前端能访问并不代表后端也是正常的。如果登录遇到502,则是后台服务器没启起来,多半是数据库的问题,可以通过以下方式排查:

  • 数据库版本,建议用8.x版本,5.7版本不支持
  • 查看后端配置文件application.properties中数据库配置是否正确
  • 可以通过前面提到的logs.log日志查看,也可以查看数据库是否自动创建相关数据表
  • 检查数据库端口及Nginx反向代理的端口在防火墙中是否放开

另外,如果前端页面访问不了,很可能是防火墙没开放权限,需要在防火墙中放开上述配置文件中配置的8888端口:

firewall-cmd --permanent --add-port=8888/tcp
firewall-cmd --reload

如果是前后端服务是部署在云服务器,需要在安全组中放开8888端口。

2.测试引擎部署

测试引擎可以理解为接口测试和UI自动化测试的运行环境。测试引擎可以选择部署在Linux系统,也可以选择使用个人Windows电脑,最好处于同一局域网下。当然如果服务端是部署在云服务上,有公网IP地址,Windows是个人办公电脑也可以,只要引擎电脑能要连上部署后端服务的那台服务器就行。以下是引擎部署过程:

1)上传代码

前面已经通过“git clone https://github.com/Chras-fu/Liuma-engine.git”克隆好了引擎代码,直接上传到对应的服务器即可,比如我选用的是Windows作为引擎,那么直接拷贝到Windows即可。

2)安装依赖

前面依赖环境部署已经安装好了Python3,创建并激活了虚拟环境,下面直接进入项目所在目录liuma-engine,安装依赖即可。

pip install -r requirements.txt

3)下载Chrome驱动

对照引擎机的Chrome浏览器版本,下载对应驱动,存放在/browser目录下

4)添加引擎

① 注册引擎

流马平台环境中心-引擎管理-注册引擎,输入引擎名称,名称任意,自己能识别即可,如:engine-192.168.1.188,确认后,会弹出一个提示框,复制里面的引擎code和引擎秘钥,后面会用到。

② 配置引擎服务器

编辑liuma-engine/config目录下的配置文件config.ini,进行配置,几个重要配置如下:

  • url:后台服务所在的URL;
  • engine-code:前面注册引擎成功后,提示框中的引擎code;
  • engine-secret:前面注册引擎成功后,提示框中的引擎秘钥;
  • options:如果引擎机是Linux系统,则改为headless,即无头模式,如果是Windows则保持默认的normal;
  • path:如果引擎机是Linux系统,则改为chromedriver,如果是Windows则保持默认的chromedriver.exe;
  • token:后面注册成功后会自动生成,可以不用管;
[Platform]
url=http://192.168.1.122:8888
enable-proxy=false
enable-stderr=true

[Engine]
engine-code=9d4358f0c8a34a2ab7e4c297949149fa
engine-secret=86a2f8f8bd654e03a60da9f19cdec017

[Header]
content-type=application/json;charset=utf-8
token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NjI2Mjk4OTQsImVuZ2luZVNlY3JldCI6IjVhM2ZhYzdlYzJiODQ4NDlhYzJhNjY4ZGRlNjRhMDk0IiwiaWF0IjoxNjYyMDI1MDk0LCJlbmdpbmVJZCI6ImU3ZWMzOTllZDdkZDRkMmFiZWIxNGNiNTE2NGNiNGVkIn0._LVsCKIauFxV4IKAUNgYS1lVbD5twO_2E39QCOufKH8

[WebDriver]
options=normal
path=chromedriver.exe

[PlatformProxy]
url=http://0.0.0.0:80
username=****
password=****

5)启动引擎

python startup.py

6)验证引擎是否添加成功

引擎启动成功后,即可在流马平台环境中心-引擎管理中查看引擎在线情况。一台服务器可以启动多个引擎,一般默认有四个系统引擎,启动后互不影响。

【使用篇】

一、接口测试

1.前置准备

在开始创建接口测试之前,我们需要先做一些最基础的准备工作,例如:注册一个项目,添加或注册一个账号,将新注册的账号添加到项目中。先看一下官方文档对项目、角色、用户的关系介绍:

注册账号

登录页面注册新账号

注册完成后,登录管理员账号,在【系统管理-用户管理】中能看到注册的用户:

创建项目

创建项目时,可以选择新注册的账号作为管理员,后续此账号登录时即可看到此项目。

2.创建接口

这个平台的最大功能是自动化测试,而我们本次的目的就是体验这个平台的自动化相关的功能好不好用,所以重点会从接口自动化测试及UI自动化测试着手。至于其他相关功能,官方使用手册的内容已经写得非常详细,这里就不做过多介绍。

接口测试需要先创建接口,在创建接口前需要先创建各个接口的执行环境,也就是域名或URL:

新增环境

① 新增域名标识

在新增环境前,需要先新增域名标识,否则在新增环境的时候无“域名标识”内容可供选择

右上角配置中心-域名标识-新增标识,填入标识名称和标识描述,确认。

② 新增环境

添加好域名标识,就可以新增环境了,添加环境的目的主要是为了后面运行测试用例的时候是基于哪套环境,比如同一个项目,可能会有开发环境、测试环境、预发环境等等:

环境中心-环境管理-新增环境,输入环境名称、环境描述,确认。

③ 新增域名

在刚新增的环境下新增域名,匹配类型选择“域名标识”,匹配标识选择第一步新建的域名标识的名称,域名填写接口请求的URL地址。同Metersphere的环境管理类似,此处新建环境后,后面发起的接口测试请求,就是基于这个环境的URL发起。

新增并填写接口信息

① 创建模块

既然是接口测试,就需要先创建接口,在新增接口前需要先创建各个模块,用于分类管理各个模块下的接口

② 新增接口

新增接口可以选择手动新增和导入两种方式,导入的方式支持文件导入、postman、swagger导入,此处我选择的是手动新增,以登录接口为例:

基础信息部分就是接口地址、描述、名称等信息,各个字段简洁明了,不再赘述;请求参数部分主要涉及到请求头、接口的请求体等。为了满足不同用户的登录需求,我的接口请求参数是采用引用变量的形式来传参。提到变量就不得不提到下面的公共参数。

新增、引用公共参数

① 流马与Metersphere的公共参数的设计上的区别

新增公共参数的目的主要是为了后面在接口中引用,类似于全局变量。Metersphere和流马都是基于项目进行管理其下的环境、变量,最顶层是项目。Metersphere的公共参数是放在环境中进行管理,它是一个环境下挂多个变量的概念,而流马中环境则是和变量进行分开,一个项目可以新增多个环境,一个项目可以新增多个公共参数,环境和公共参数之间互不干扰。

公共组件-公共参数-自定义参数-新增自定义参数,填入参数名称、类型、参数值等。注意:同一项目下变量名称不可重复。例如,新增一个登录用户名的公共参数:

② 流马公共参数引用

Metersphere对于公共参数的引用与Jmeter一致,都是采用${name}的形式,而在流马中,则是通过{{$username}}形式进行引用,与postman类似,但比postman多了个$符,postman是{{username}}。请求头和请求体中都可以通过此种方式引用公共参数,但是要注意参数的类型,请求头中一般都是string类型的参数。

内置函数

与Jmeter类似,流马中内置了函数助手,提供很多函数可供选择

比如我的某个接口传参中需要一些指定长度的随机数字,那么则可以使用random_number函数,引用方式见下图标:

添加、引用自定义函数

某些情况下,内置函数可能无法满足生成参数的需求,这是则可以创建一些自定义函数。按照官网文档的介绍,平台支持Python Faker库的方法(毕竟执行引擎就是Python),那么我们就可以创建一个Python方法来自定义生成一些参数。不过有一点需要注意,函数的返回值要使用sys_return(value)来返回

① 创建自定义函数

例如我想生成随机手机号,则可以通过如下方式常见:公共组件-函数管理-新增函数,内容如下:

可以看出,语法其实就是Python语法,只不过最后的返回值使用了sys_return代替。

② 引用自定义函数

添加完自定义函数,就可以在接口传参中引用,方式为:{{@function()}}

其实上述三个参数:姓名、手机号、身份证号我都是通过自定义函数来生成的。最后发起请求时,通过日志可以看到生成的参数值:

特别注意

有个很重要的细节需要注意,也是我在使用过程中遇到的一些小坑:

接口传参中引用string类型的公共参数时需要加引号

定义参数时,如果是string类型变量:

  • 参数值没加引号、在传参时不会自动带上引号
  • 也不能在定义变量时给参数值加上引号
  • 只能在接口引用变量时,外层带上双引号

举个例子可能会直白一点:

假如我们登录接口需要传入密码参数,而我们提前在公共参数中定义了这个变量password,值为e10adc3949ba59abbe56e057f20f883e,是一个string类型,如下图所示:

假如值没加双引号的话,传参的时候不会自动带上引号(通过执行打印结果可以看出),哪怕定义时选择的是string类型,被测接口的服务端也会认为它不是一个string类型

如果我们在公共参数中手动给它加上双引号,此时执行引擎Python那边就会报错JSONDecodeError

解决办法是在定义公共参数时不加引号,在接口中引用参数时,加上引号

此时就会识别成合法的string类型值:

3.测试用例

创建用例并添加接口

添加模块,新增用例页面:

一条用例是由一个or多个接口组合而成,从而形成不同场景的业务流。前面接口管理中新建接口后,就可以在用例中选择添加该接口,一次可选择单个或多个。

添加断言

断言的类型有多种,比如某个添加用户的接口,添加成功后返回值是{"a":"200","d":"30200"},其中a是固定的,即接口响应码,d的值用户ID,是不固定的,那么这里就可以通过jsonpath提取器先提取d节点的值,用“整数”来进行断言:

导入配置信息

如果某些接口用到了自定义的函数(内置函数不需要导入)、公共参数、公共header等,则需要在用例中一一将它们选择导入,否则接口中引用不会生效。很多时候,用例执行不同都是因为没有导入这些元素导致:

关联参数

通常,一条用例可能会包含多个接口,而接口参数之间可能会相互关联,比如B接口的入参用到A接口的出参,就需要先提取A接口的出参,再在B接口中进行引用。

① 提取返回值

与Jmeter和Metersphere一样,提取返回值支持正则表达式和jsonpath提取两种方式,与与Jmeter和Metersphere不同的是,流马提取返回值时,表达式不需要加$符号:

② 引用返回值

与前面引用公共参数不同,引用返回值的{{}}内不需要加$符号,直接填写变量名即可:

特别注意

接口管理与用例管理中的接口信息不同步

若用例中添加了接口A,则:

  • 编辑接口A详情后,编辑后的内容不会同步到接口管理的接口A中;
  • 在接口管理中编辑接口A,也不会同步到用例中的接口A;

比如我们创建了一条用例,其中添加了接口A,并在用例中给接口A添加了一个请求头参数,此时,到接口管理中查看接口A则不会同步这个请求头参数;而在接口管理中添加的请求头参数也不会同步到用例中,相当于用例管理和接口管理做了隔离。此时就需要两边各修改一次接口A,或是在接口管理中修改后再重新添加到用例中。

说实话我觉得这个设计很不好用,因为在现实使用中,会有很多测试用例用到同一个接口。举个例子,如果我只在测试用例A中添加或更改了某个接口的请求头,那么其他测试用例B、C、D中则需要一一更改。

起初我以为是bug,后来特地问了作者,就是这么设计的,也不是不能改,只是处理起来会很麻烦,而且很多其他平台也都是这么设计的,后期会慢慢优化。

4.业务流程测试实践

此处以在测试中常见的某个业务流程场景为例,来串联前面提到的公共参数、自定义函数、关联参数等等,流程如下:用户登录->添加一个商品->获取商品详情->删除商品,从添加到删除,这样既形成了一个小的业务流程的闭环,也避免我们后期到数据库中手动删除数据,这也是现在接口流程测试中一种较为常见的做法。

完善用例信息

一个完善的业务流程的测试用例,通常需要做以下工作:

  • 填写基础信息;
  • 导入配置信息:自定义函数、公共参数、共用header;
  • 添加接口并调整好接口顺序;
  • 为每个接口添加合适的断言;
  • 配置接口之间的关联取值;

执行用例

分别看下各个接口的执行结果,并做一些简单的解读,看其是否符合最初的流程设计:

① 登录接口

账号登录成功,并获取到返回值,返回账号的user id及token信息。

② 新增商品

新增商品成功,返回d节点为商品的ID。

接口断言返回值的d节点为整数,断言成功。关联参数会提取d节点的值,作为后面接口的入参。

③ 获取商品详情

上一个接口提取的商品ID,已经传入请求体,并获取到了商品详情。

接口断言返回值的d节点的aa节点与商品ID变量数字相等,断言成功。

④ 删除商品

此处接口传参使用的也是新增商品返回的商品ID作为入参,删除成功d节点返回值为1

接口断言返回值的d节点数字恒等于1,断言成功

二、web自动化测试

web自动化测试我研究得确实不多,我想它的设计理念应该是和接口测试类似的,比如:

  • 封装了selenium webdriver的一些方法,如浏览器窗口最大化、最小化等作为内置方法;
  • 元素管理可以类比成接口管理,里面是一个个的页面元素;
  • 用例可以类比成接口用例,接口用例由一个个接口组合而成,而UI用例由一个个元素及元素操作组合而成。

1.元素管理

添加元素

以百度首页为例,添加百度首页的一些元素,如:搜索框、百度一下按钮。定位方式支持selenium的八大元素定位方式

表达式直接填写元素属性值,比如ID定位,搜索框的ID属性值是kw

如果选择name定位,表达式就填wd

元素列表

元素列表管理所有元素,建议不同页面可以通过不同模块来进行管理,这也符合UI自动化PO设计模式中一个很重要的设计原则:同一个页面,只管理本页面下的页面元素对象。

2.测试用例

新增操作

新增操作基本上涵盖了UI自动化测试中所有可能用到的操作,比如:浏览器最大化、断言、IF...ELSE、切换frame等

添加元素

这里有个小点需要特别注意,按照我原本编写测试脚本的固化思维是:先声明元素对象>>再附加元素动作,比如点击、双击、滑动、长按等,所以也想当然地先来添加元素,结果摸索了半天没找到入口。但其实是先选择操作的动作,如输入、单击>>再选择要操作的事先录入好的元素:

当然在操作设置页面、勾选元素后面的按钮后,也可以新建页面元素对象:

3.测试场景实践

设计测试场景

此处以百度搜索作为一个小小的测试场景,来串联前面提到的元素定位、添加元素等,场景流程如下:

打开浏览器>>打开百度首页>>最大化浏览器窗口>>输入框输入“流马”>>提交搜索>>断言页面标题包含“流马”>>等待三秒>>关闭浏览器

测试效果

三、测试计划

测试计划作用是确定测试执行的全部用例,以测试集合为维度管理。此外测试计划支持定时任务和周期执行。同时测试计划按照版本管理,也支持集成到研发流水线。

1.测试集合

编辑集合

测试集合可以看作是多个测试用例的集合,每条用例相互独立、互不影响。填写集合相关信息,注意版本要在配置中心提前新建好。

添加测试用例

添加用例,可以选择到之前创建的各个测试用例,API用例和UI用例可以同时选择,按照顺序混合执行。

创建完的集合,可以手动执行,也可以创建测试计划定期或周期性执行

测试计划

手动执行测试集合,生成测试报告

2.测试计划

编辑计划

填写名称、选择版本、执行引擎、设置执行时间

执行频率有多种方式可供选择,类似于Jenkins或是Linux crontab的定时任务:

新增集合

测试计划需要选择测试集合,前面新建的集合在这里会选择到,一个测试计划可以包含多个测试集合

【总结篇】

一、使用总结

1.常见注意事项

  1. 引用公共参数:{{$name}},带上$符
  2. jsonpath提取前一个接口返回值,表达式不同于Jmeter,没有最外层的 $.
  3. 引用前一个接口提取的参数:{{name}},没有$符
  4. 引用内置函数:{{@function_name()}},注意有@符,括号内为函数的参数
  5. 自定义参数:可以使用Python语法,但返回值要使用sys_return(value)来返回
  6. 接口header和用例断言中都可以引用公共参数和提取的变量,但是提取的变量值传参时如果类型不同、需要提前转换类型
  7. 用例中,如果用到了一些自定义的公共参数或自定义函数,需要将其一一勾选导入,用例才能生效
  8. UI用例,先选择要执行的动作,才能选择到要执行的元素
  9. 对于流马而言,最大的是项目,一个项目可以包含多个测试计划,一个测试计划可以包含多个测试集合,一个测试集合可以包含多条测试用例,一条测试用例可以包含多个接口或UI元素对象

2.优化建议

在使用中我也遇到了一些麻烦,有的是自己摸索解决的,有的是靠用户手册解决,有的则是在用户交流群中咨询解决的,我想肯定有人和我遇到同样的问题或是使用感受。以下是我总结出的一些优化建议,仅代表个人:

① 接口复用

目前用例管理中支持用例复用,也就是复制的功能,但接口管理不支持,如果当前有一些接口,内容都比较相似、仅仅修改接口地址和个别参数就可以使用,那么增加这个功能就显得很有必要。

② 关联参数增加自动转换功能

这个也是我在使用过程中遇到的问题,比如我从A接口提取了返回值user_id需要传到下一个B接口的请求头中,提取的user_id值是一个int类型,而传到B接口的请求头中需要string类型:

① 如果通过{{user_id}}引用提取的变量值的话,B接口请求时就会报类型错误;

② 如果通过'{{user_id}}'引用提取的变量值的话,B接口请求时就会报错502;

目前作者给的解决方案是在前置脚本里处理,或是写个自定义转换的函数

如果能在编辑用例---添加请求头的时候直接选择类型就好了,类似于编辑接口管理下这样:

③ 标题超链接跳转

目前标题只有一级“首页”支持跳转,二级、三级不支持超链接,如果当前页面处于一个很深的层级,那么标题跳转显然会比浏览器的后退、前进更加自由灵活。

④ 固定侧边栏

目前刷新页面后,侧边栏会自动收缩,建议可以参考Metersphere以及微信聊天窗口等类似的做法,加一个固定按钮,可以固定/取消固定侧边栏。

⑤ 设置默认执行引擎

目前每次执行都需要选择一次执行引擎,次数多了操作起来就会比较麻烦。建议可以设置默认执行引擎或修改执行引擎列表顺序。

⑥ 自动填充模块分类

点击模块名称会查询当前模块下的接口,而此时处于某个模块下、进入新增接口页面时,仍需选择一次所属模块,建议可以增加自动填充模块分类功能。

⑦ 弹框关闭二次确认

假如我正在编辑某个弹框,且编辑了很多内容,此时如果一不小心鼠标点到了其他空白处,弹框就是自动消失,原本编辑的字段也需要再重新编辑。如果点击其他空白处,可以弹出一个二次确认弹框,会避免很多误操作。

二、优缺点总结

以上这些都是我亲自使用过程中的总结体会。所谓“实践是检验真理的唯一标准”,一个工具/平台好不好用,不是靠听别人说的,而是要自己试了才知道。

1.优点

① 设计巧妙

正如前面项目概述提到的“项目分为平台端和引擎端,采用分布式执行设计,可以将测试执行的节点(即引擎)注册在任意环境的任意一台机器上,从而突破资源及网络限制。同时,通过将引擎启动在本地PC上,方便用户快速调试测试用例,实时查看执行过程,带来传统脚本编写一致的便捷。

也就是说执行引擎和前后台服务是独立开来的,执行引擎既可以部署在Linux,也可以部署在Windows,也可以使用个人办公电脑,从而快速调试。

另外一个巧妙的地方我觉得没有那么多套路,基本上上手一遍就能摸索出规律,例如前面提到的:一条用例包含多个接口,相应的就能想到计划包含集合、集合包含用例、用例包含接口或元素对象。

② 功能强大

支持接口测试、WEB测试、APP测试,支持定时任务、周期性执行、并发执行

③ 使用灵活

平台技术栈:前端VUE+ElementUI,后台Java+SpringBoot,测试引擎Python,支持Python自定义函数,相对了解Python编码的测试工程师来说较为友好,使用起来会更灵活。

2.缺点

① 部分细节功能不完善

部分细节功能不完善、或者说不好用。比如前面提到的优化建议,以及一些注意事项,都是我在使用过程中遇到并总结的。

② 上手成本略高

流马的定位是低代码测试平台,旨在帮助不懂代码的测试工程师也可以自由地开展多种类型的自动化测试。我自认为稍微懂一点点代码,也见识过一些开源平台,但在使用过程中,确实也摸索了几天。注意,这里的上手指的是开展公司的实际测试业务,而不是请求一个百度接口或是打开一个百度页面这种demo这么简单,要能把公司的业务迁移到平台并成功运行起来,这意味着肯定要花费一定的时间学习和摸索、以及解决使用过程中遇到的问题。

③ 用户手册不够详细

用户手册的内容相较于Metersphere确实不够详细,很多都是一个简短的描述,没有具体用法示例,这也就造成了遇到一些问题时可参考的内容较少。不过这也能理解,毕竟MS背后是商业化的公司,有充足的人力可以维护和更新文档,而流马据我所知只有作者一人维护。

3.总结评分

由于篇幅、个人时间以及能力限制,只罗列了上述有限的功能和使用细节,更多精彩功能还需大家亲自部署体验。按照惯例,简单对流马做个评分总结,评分过程中可能稍带有主观色彩,毕竟我也是用户,但会尽量本着客观公众的原则。评测还是基于之前预告篇中的维度。

特别声明:由于每个人的关注点不一样,所以评判标准可能也会有所偏差

测评维度

详细说明

评分(星级越高,得分越高)

环境搭建

1.依赖环境:较多,支持容器化部署,传统部署相对较繁琐些

2.搭建难度(难度越大、星级越低):对新手来说难度会较大,因为涉及的工具和服务比较多

☆☆☆

用例管理

1.是否支持导入用例:支持多种平台及格式导入

2.用例执行顺序编排:支持,可以拖动

☆☆☆☆☆

接口测试

1.单接口测试:支持,不过没看到导入CSV入口,参数化和数据驱动支持情况不详

2.接口流程测试:支持,多种参数提取方式,支持测试集合、测试计划,可以定期或周期性执行

3.自动生成测试报告:支持,简洁

☆☆☆☆☆

UI自动化测试

1.APP:支持

2.Web:支持

☆☆☆☆☆

性能测试

不支持

扩展功能

1.是否支持二开:支持

2.是否支持定时任务:支持

3.是否支持接入CICD:支持

4.是否支持测试结果度量:支持

5.用户权限配置:支持,不同用户不同权限

6.测试管理:不支持,平台定位不是如此

7.缺陷跟踪:不支持,平台定位不是如此

☆☆☆☆☆

其他

1.文档支持(部署教程、操作手册):不够详细

2.代码更新维护频率:长期维护

3.社区活跃度:中等

4.易用性:上手成本略高

5.稳定性:目前暂未发现bug

☆☆☆☆

最后总结:流马功能强大,支持多种类型的自动化测试,可以满足各种自动化测试需求;平台定位低代码、易使用,能够帮助没有代码基础的测试工程师也能快速开展自动化测试,不过平台使用过程需要一定的学习和摸索成本,部分细节功能还需优化完善。作为个人开发者开发的流马平台,能做到现在这样的效果,确实非常厉害,值得点赞和学习!任何一个开源项目,既需要接受用户的批评、质疑、意见建议,也需要用户的包容、鼓励和支持,有了一定的用户基础,大家群策群力,项目才会越来越好,带来更多价值!