上一節(jié)中我們學(xué)會了安裝TypeScript支持,以及創(chuàng)建了一個基本的Angular工程。并嘗試啟動了工程,看到了首頁。
本節(jié)內(nèi)容中,我們要學(xué)會做我們的第一個頁面,登錄頁面。
同時我們要學(xué)會集成我們使用的UI框架Ant Design For Angular,NG-ZORRO。
Ant Design :源自螞蟻金服體驗(yàn)技術(shù)部的后臺產(chǎn)品開發(fā),螞蟻金服的設(shè)計師和前端工程師經(jīng)過大量的項(xiàng)目實(shí)踐和總結(jié),抽象出的一套企業(yè)級的交互視覺規(guī)范,統(tǒng)一后臺項(xiàng)目的前端 UI 設(shè)計,屏蔽各種不必要的設(shè)計差異和前端實(shí)現(xiàn)成本,解放設(shè)計和前端開發(fā)資源。Ant Design提供了對Angular、Vue、React等前端框架的支持。
NG-ZORRO:是遵循 Ant Design 設(shè)計規(guī)范的 Angular UI 組件庫,主要用于研發(fā)企業(yè)級中后臺產(chǎn)品。全部代碼開源并遵循 MIT 協(xié)議,任何企業(yè)、組織及個人均可免費(fèi)使用。
官方網(wǎng)站可參考:https://ng.ant.design/docs/introduce/zh
1、自動安裝
只需要進(jìn)入我們的工程目錄,執(zhí)行如下命令即可:
ng add ng-zorro-antd
VSCode中,步驟如下:
選擇菜單欄中的終端(Terminal) - 新建終端(New Terminal),然后在新的終端窗口中輸入上面的命令即可。
安裝時會有選項(xiàng)提示,根據(jù)需要選擇即可。
這樣會自動安裝成功NG-ZORRO。
我們可以啟動工程看一下:
已經(jīng)為我們配置了一個歡迎主頁面,使用了側(cè)邊欄,而且側(cè)邊邊欄是可以自動收縮的。
2、我們也可以手動安裝NG-ZORRO
首先,在工程目錄下,執(zhí)行安裝組件命令:
npm install ng-zorro-antd --save
接著,我們引用樣式:
在 angular.json 中引入:
{
"styles": [
"node_modules/ng-zorro-antd/ng-zorro-antd.min.css"
]
}
在 style.css 中引入預(yù)構(gòu)建樣式文件:
@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>
登錄頁面主要顯示的都是表單,因此需要引入表單組件,在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 { }
上述代碼中忽略了 既有的其他代碼。我們只需要導(dǎo)入包:
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即可。
切換到我們工程下的pages目錄,完整路徑:src/app/pages/。我們所有的頁面都會放在這個目錄下維護(hù)。
然后輸入如下命令,創(chuàng)建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>
第一次執(zhí)行ng generate component login命令時提示More than one module matches,我們只需要加入--skip-import 參數(shù)即可。
生成的代碼如下:
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="用戶名/手機(jī)/郵箱" />
</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'; // 導(dǎo)入構(gòu)建表單需要的相關(guān)組件
import { Router } from '@angular/router'; // 導(dǎo)入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 {
// 構(gòu)建表單對象
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();
}
// 表單驗(yàn)證失敗返回
if (this.validateForm.invalid) {
return;
}
// 表單驗(yàn)證通過,調(diào)用登錄邏輯
// 登錄代碼忽略
// 登錄成功跳轉(zhuǎn)到welcome 頁面
this.router.navigate(['welcome']);
}
}
我們修改路由把登錄頁面設(shè)置為默認(rèn)加載頁面:
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' }, // 當(dāng)前網(wǎng)站根
{ path: 'login', component: LoginComponent, data: { title: '登錄' } },
{ path: 'welcome', component: WelcomeComponent }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
我們修改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 { }
代碼中我忽略了不相干的代碼。
我們啟動工程來看一下效果:
直接點(diǎn)擊登錄看一下:
我們隨便輸入一個用戶名和密碼,點(diǎn)擊登錄看看:
成功地跳轉(zhuǎn)到了welcome頁面。
本篇教程中我們學(xué)習(xí)了如何集成NG-ZORRO到Angular工程中,然后我們嘗試著,使用NG-ZORRO的表單組件,構(gòu)建了一個登錄頁面。并配置了網(wǎng)站的默認(rèn)頁面為登錄頁面。大家可以看到 使用Angular + NG-ZORRO構(gòu)建一個前端的網(wǎng)站是如此簡單。
沒上手 OPPO Find N 之前,筆者對折疊屏并無太大興趣,一方面,筆者更看重手機(jī)的實(shí)用性,折疊屏雖然有更明顯的大屏優(yōu)勢,但過萬的售價,以及折痕、應(yīng)用適配等一系列問題,隨便挑一點(diǎn)就足以“絕殺”;另一方面,則是在 OPPO Find N 之前,筆者已經(jīng)陸續(xù)上手過其他折疊屏手機(jī),對折疊屏的新鮮感早已褪去。
那么為什么 OPPO Find N 的發(fā)布卻讓筆者興奮了很久?同樣來自兩個方面的原因:
其一,OPPO Find N 在形態(tài)方面有了很大的改進(jìn),特別是外屏不再是夸張的瘦長以及主打的“隱痕”,非常值得體驗(yàn)一番;
其二,F(xiàn)ind N 7699 元的起售價聽起來相當(dāng)?shù)恼T人,幾乎與一臺 Pro 版本的 iPhone 相當(dāng),這也意味著折疊屏手機(jī)定價至少不再“高不可攀”。
在 OPPO Find N 發(fā)布之后,筆者便選擇將 OPPO Find N 作為主力機(jī)使用至今,那么這一段時間來,OPPO Find N 都帶來了哪些不一樣的體驗(yàn)感受?又解決了哪些折疊屏手機(jī)中存在的問題?
本篇文章,IT之家將圍繞 OPPO Find N 的大小屏、折疊形態(tài)、應(yīng)用交互、游戲體驗(yàn)等方面深入體驗(yàn),詳細(xì)和大家分享一下 OPPO Find N 的用機(jī)感受。
OPPO Find N 依舊延續(xù)了 OPPO 產(chǎn)品慣有的精致感,中框采用了拋光金屬設(shè)計,看起來很有一種瑩潤、精致的質(zhì)感。
鉸鏈外露的部分做了拋光加凹陷噴砂搭配的設(shè)計,在凹陷區(qū)域,還印有“DESIGNED FOR FIND”的文字,高級感一下就上來了。
手機(jī)的外屏、背板均采用 3D 微曲面設(shè)計,保證顯示畫面視覺平衡的同時,也更加貼合手掌。
再看手機(jī)的背面,延續(xù)了 Find 系列“流體曲線”的設(shè)計語言,影像模組還是環(huán)形山曲面設(shè)計,可惜并沒有采用 Find X3 系列的一體化曲面,因此視覺和觸覺上,是存在一定割裂感的。
OPPO Find N 背板部分頂部有一枚麥克風(fēng),側(cè)邊是指紋識別電源二合一按鍵,底部是揚(yáng)聲器、USB Type-C 接口和麥克風(fēng)。不過,折疊狀態(tài)下,音量鍵和指紋鍵過于靠近,很容易誤觸。
OPPO Find N 采用了雙 box 立體聲雙揚(yáng)聲器,支持杜比全景聲,出色的音質(zhì)表現(xiàn)是毋庸置疑。不過這兩枚揚(yáng)聲器均位于機(jī)身底部,因此在使用過程中,聲音仍是來自一個方向,這一點(diǎn)有些吃虧。
OPPO Find N 內(nèi)置的 X 軸線性馬達(dá),OPPO 調(diào)教的非常出色,包括后臺清理、指紋解鎖等等場景下,以及鍵盤輸入(仿真鍵盤)的震動反饋,都非常的細(xì)膩真實(shí),可以說是安卓陣營第一梯隊(duì)了,必須好評。
折疊狀態(tài)下,OPPO Find N 的三圍尺寸分別是 132.6mm、73mm、15.9mm,重量為 275g,不看厚度和重量,妥妥的小屏機(jī)。275g 重量在折疊屏手機(jī)中也屬于很輕的了,不過,因?yàn)?OPPO Find N 尺寸小,握持時重量會集中在手掌中,所以會產(chǎn)生較為明顯的墜手感。
當(dāng)然,展開之后上述問題都會解決,大屏?xí)⑦@部分重量和厚度均勻出去,所以雙手握持就非常舒適了。
不同于之前的折疊屏手機(jī)折疊后的“遙控器”形態(tài),當(dāng) OPPO Find N 合上時,5.49 英寸、18:9 的屏幕讓它看起來就像一款正常的傳統(tǒng)小屏手機(jī),單手就可以握持掌控。不過,在折疊狀態(tài)下,OPPO Find N 是存在一定的機(jī)身厚度的,更像是兩臺 iPhone12 mini 疊加在一起,所以,在各種角度下看折疊狀態(tài)下的 OPPO Find N,都有種“萌胖”的感覺。
將 OPPO Find N 展開后,就成了屏幕 7.1 英寸的小平板,8.4:9 的比例在觀感上像是一塊正方形。此外,OPPO Find N 在展開狀態(tài)下,打開應(yīng)用就可以直接使用,而不是像其它折疊屏手機(jī)那樣,需要先旋轉(zhuǎn)一下角度。
這塊 AMOLED 柔性內(nèi)屏采用了三星 E5 材質(zhì),支持 LTPO,支持 1-120Hz 自適應(yīng)刷新率,內(nèi)屏展開之后能夠帶來尤為震撼的視覺沖擊力。
外屏方面,OPPO Find N 同樣采用了 AMOLED 柔性屏,同樣支持 100% P3 色域,1972 × 988 的分辨率和 60Hz 刷新率可以滿足日常使用。不過,當(dāng)你從外屏切換至內(nèi)屏、從內(nèi)屏切換至外屏?xí)r,在體驗(yàn)上會稍顯割裂感。
即便如此,筆者認(rèn)為 OPPO Find N 的這塊外屏仍是可圈可點(diǎn)的,其最大的優(yōu)勢并不是在參數(shù)規(guī)格,而是在于形態(tài)方面 ——
部分折疊屏手機(jī)的外屏都采用了非常夸張的顯示比例,折疊狀態(tài)下握在手中像是拿著一臺遙控器,夸張的顯示比例甚至還會出現(xiàn)畫面裁切等問題(比如刷抖音時,畫面兩側(cè)會有切割),嚴(yán)重影響體驗(yàn)。相比之下,OPPO Find N 外屏的優(yōu)勢非常明顯,18:9 的顯示比例就是一塊再正常不過的全面屏,應(yīng)用無需額外的優(yōu)化適配,如果你愿意,完全可以當(dāng)作主屏全天候使用。
OPPO Find N 還給出了大小屏接力功能 。
折疊屏手機(jī)內(nèi)屏轉(zhuǎn)外屏使用過程中,存在一個交互邏輯,比如我把折疊屏合上,此時手機(jī)并不知道我是否要繼續(xù)使用外屏,很多折疊屏給出的方案是,內(nèi)屏合上了,外屏自動點(diǎn)亮,如果我不想用了,還需要再按一下電源鍵才能放回口袋。
OPPO Find N 的大小屏接力,內(nèi)屏折疊之后,小屏?xí)霈F(xiàn)上滑提示,上滑繼續(xù)內(nèi)屏的內(nèi)容瀏覽,應(yīng)用銜接更是做得非常流暢;你也可以直接放進(jìn)口袋(3 秒無操作自動息屏),這種交互邏輯顯然要更人性化一些。
(大小屏接力 GIF 演示)
折痕是折疊屏手機(jī)目前存在最大的問題之一,準(zhǔn)確的講,OPPO Find N 并沒有消滅折痕,而是將“折痕問題”給淡化了,它不會讓你在使用手機(jī)的過程中因?yàn)槠聊恢醒氲恼酆鄯址昼姟俺鰬颉保聦?shí)上筆者在使用 OPPO Find N 的這段時間,“折痕”真的可以忽略不計,展開后屏幕一體感更強(qiáng),也讓筆者更愿意在展開狀態(tài)下使用 Find N。
和此前的折疊屏手機(jī)相比,OPPO Find N 采用了“用折痕面積換折痕深度”的思路,內(nèi)屏是以“水滴”的形狀折疊,折痕區(qū)域的面積比較大,但折痕非常淺,息屏狀態(tài)下,只有在不同角度的光線下才能感受到,或者是用指甲蓋在內(nèi)屏中央滑動,才感受到屏幕是不平整的。日常使用過程中,我想沒有幾個折疊屏用戶會在意這些細(xì)節(jié)。
如果有人非盯著折痕問題不放,那顯然也不是折疊屏手機(jī)的潛在用戶了,舉個不恰當(dāng)?shù)睦樱私馊讬C(jī)的用戶遠(yuǎn)比買過三缸機(jī)的用戶更在意抖動問題。
OPPO Find N 所實(shí)現(xiàn)的“微痕”,跟 OPPO“水滴鉸鏈”有很大關(guān)系,配合 OPPO 的研發(fā)調(diào)校,最終實(shí)現(xiàn)了幾乎無折痕。
當(dāng) OPPO Find N 折疊屏合上后,屏幕四邊的貼合很緊密,因此不用擔(dān)心日常使用會鉆進(jìn)沙子灰塵等劃傷屏幕。同時 UTG 使得內(nèi)屏硬度更高,對一些有美甲的女性用戶比較友好。
根據(jù) OPPO 介紹,F(xiàn)ind N 經(jīng)過萊茵 20W + 折疊無憂認(rèn)證,哪怕每天折疊 100 次,壽命也可以堅(jiān)持超過 5 年。筆者使用 OPPO Find N 的這段時間來,平均每天折疊次數(shù)達(dá)到了百次 +,但現(xiàn)在看來,仍是沒有任何問題的。
OPPO Find N 的“水滴鉸鏈”還實(shí)現(xiàn)了不錯的懸停功能。即便是在日常使用中懸停功能我用的并不是很多,但個人還是要吹一波:
它實(shí)現(xiàn)了手機(jī)在折疊、展開之外的第三種使用形態(tài)“懸停交互”,給折疊屏手機(jī)留下了很大的想象空間,比如游戲開發(fā)者完全可以借助 OPPO Find N 的折疊優(yōu)勢和硬件形態(tài),開發(fā)出類似任天堂 3DS 游戲機(jī)這樣的操作和玩法體驗(yàn)。
(懸停交互 GIF 演示)
OPPO Find N 支持 50° 到 120° 任意角度的自由懸停,并且?guī)砹藨彝z影、懸停觀影、懸停視頻通話、懸停會議等等功能。
以相機(jī)懸停為例,拍攝一些長曝光樣張,或者是延時攝影,往往需要配合三腳架,而在懸停模式下,OPPO Find N 下半部分就可以作為“三腳架”固定在平面上。
(懸停攝影 GIF 演示)
再比如懸停觀影,將屏幕調(diào)整至任意角度放在桌面,就可以一半屏幕播放影片,一半屏幕進(jìn)行操控。
(懸停觀影 GIF 演示)
懸停視頻通話,把手機(jī)“立”在桌面,就能解放雙手,一邊通話一邊做別的事了。懸停視頻通話目前支持 QQ,開啟后,上屏通話界面五五開左右分布畫面,下屏顯示控制按鈕,雙方都看得清對方。
(懸停視頻通話 GIF 演示)
可見,OPPO Find N 不僅在折疊屏的硬件品質(zhì)上做了創(chuàng)新與打磨,更沒有浪費(fèi)折疊屏的天然優(yōu)勢,挖掘了很多與折疊相關(guān)的細(xì)節(jié)功能。
折疊屏在展開狀態(tài)下,嚴(yán)格意義上講就是一臺安卓平板,因此折疊屏好不好用,很大程度上在于大屏應(yīng)用的適配和交互優(yōu)化上,這也非常考驗(yàn)折疊屏廠商的軟實(shí)力。
應(yīng)用體驗(yàn)部分,首先要單獨(dú)講一下微信。
在 OPPO Find N 等折疊屏手機(jī)中,微信是可以以平板模式登錄的,跟手機(jī)上登錄的微信不沖突,也就是說可以同時登錄手機(jī)微信和折疊屏微信(平板),這對于雙機(jī)黨用戶來說,無疑是一個意外的驚喜。
據(jù)筆者觀察,很多折疊屏用戶都是雙機(jī)黨,有一臺直屏機(jī)作為主力機(jī)或備用,兩臺設(shè)備同時登錄微信,省去了來回登錄微信的繁瑣(每次都要登錄密碼,聊天記錄還不同步),這簡直是微信最良心的功能了。
在大屏狀態(tài)下,OPPO 還優(yōu)化了輸入法使用體驗(yàn)。比如輸入法布局上,OPPO 設(shè)計了分離式鍵盤,同時還精密測量了上百位用戶握持姿勢,對輸入?yún)^(qū)域進(jìn)行了優(yōu)化,讓打字體驗(yàn)更自然、舒適。
(輸入法 GIF 演示)
客觀來講,OPPO Find N 在諸如觀影、游戲以及部分應(yīng)用等場景下,相較于傳統(tǒng)直板機(jī),并沒太明顯的大屏優(yōu)勢,比如現(xiàn)如今 21:9 的電影根本無法鋪滿 OPPO Find N 這塊接近 1:1 的 7.1 英寸內(nèi)屏,上下的黑邊會造成屏幕空間的極大浪費(fèi),電影顯示面積甚至還沒有傳統(tǒng)的手機(jī)大。這也是目前所有折疊屏手機(jī)都存在的“問題”。
(21:9 電影,F(xiàn)ind N 顯示面積比傳統(tǒng) 6.5 英寸直板手機(jī)要小一些)
看到這里你或許會吐槽,折疊屏既然有大屏卻無法充分利用,那買折疊屏圖啥?事實(shí)上這也是筆者剛接觸折疊屏?xí)r產(chǎn)生的疑惑。不過在長時間體驗(yàn) OPPO Find N 之后,上述觀點(diǎn)已經(jīng)有了改變。
首先,21:9 的電影對 OPPO Find N 確實(shí)并不友好(但幾十年前的老電影非常友好,比如貓和老鼠,銀幕比例 4:3,畫面基本就能全部鋪滿),這是客觀存在的問題,需要每一位對折疊屏手機(jī)有購買意向的用戶都知曉。但是,在現(xiàn)代電影之外,諸如嗶哩嗶哩等視頻平臺,視頻、直播大多都是以 16:9 的比例呈現(xiàn),在 16:9 的比例下,雖然畫面仍不能填滿 OPPO Find N,但畫面顯示面積事實(shí)上是要比傳統(tǒng)的直板手機(jī)更大一些的。
(16:9 視頻畫面,F(xiàn)ind N 顯示面積比傳統(tǒng) 6.5 英寸直板手機(jī)更大)
其次,OPPO Find N 觀影時的上下黑邊,剛好給彈幕留下了顯示空間,不會遮擋畫面。
(無論是優(yōu)酷視頻還是B站,彈幕都盡可能的顯示在上黑邊區(qū)域)
OPPO Find N 的大屏優(yōu)勢,更適合在文字閱讀、圖片瀏覽等應(yīng)用場景使用,比如微信閱讀,大量的文字內(nèi)容可以全部鋪滿屏幕,用 OPPO Find N 看小說、看漫畫,簡直就是神器。
再比如刷微信朋友圈、公眾號文章、刷微博、論壇等等,更大的配圖帶來了更強(qiáng)的視覺沖擊力,朋友圈圖片更是點(diǎn)擊就直接鋪滿屏幕,無需雙擊屏幕放大。
(不同應(yīng)用場景下的大屏體驗(yàn))
買來折疊屏只用來看圖?文字?豈不是有點(diǎn)浪費(fèi)?如何進(jìn)一步放大 OPPO Find N 的大屏優(yōu)勢呢?這就需要 OPPO 的軟實(shí)力了。OPPO Find N 在系統(tǒng)設(shè)置內(nèi),專門加入了一個“大屏專區(qū)”,諸如自由浮窗、應(yīng)用分屏、懸停模式、兼容模式、平行視窗... 與大屏有關(guān)的所有設(shè)置和功能,都能在“大屏專區(qū)”內(nèi)可以找到。
首先是應(yīng)用分屏,要想折疊屏手機(jī)用的爽,這個功能必不可少。
應(yīng)用分屏,簡單理解就是 OPPO Find N 內(nèi)屏分為兩半,可以同時打開兩個 App 使用(一臺手機(jī)當(dāng)兩臺用)。OPPO Find N 給出的分屏方法也相當(dāng)?shù)暮唵危?App 展開的情況下,雙指在屏幕中間從上往下“一劃”,就直接分屏了,交互非常直接。
(應(yīng)用分屏 GIF 演示)
分屏狀態(tài)下,不同應(yīng)用間圖片、文字、文件,可以自由拖拽,比如看新聞的時候想記錄筆記,就可以輕松將新聞的段落拖拽到便簽中。再比如一邊微信聊天一邊逛淘寶等等。
左右拖動屏幕中央的三個小點(diǎn),還能讓兩款分屏應(yīng)用獲得不同的分屏面積,非常貼心。
如果你經(jīng)常使用某兩款應(yīng)用分屏,還可以將這個分屏組合保存在桌面,下次點(diǎn)擊一下就能直接用這兩個應(yīng)用進(jìn)行分屏,這就更加高效了。
一個大屏同時顯示兩個應(yīng)用,大屏優(yōu)勢這不就體現(xiàn)出來了?
不過,在分屏狀態(tài)下,退出其中的一款應(yīng)用之后,OPPO Find N 就立馬結(jié)束了分屏狀態(tài),此時另外一款應(yīng)用就直接拉伸鋪滿了整個屏幕,想要再分屏另外一個應(yīng)用就得重新操作一番,這一點(diǎn)筆者不是很理解。
OPPO Find N 的大屏,給了“自由浮窗”更大的使用空間,而 OPPO Find N 呼出小窗的方法也是非常簡單,全屏狀態(tài)下,屏內(nèi)四指收縮,即可迅速調(diào)出小窗模式。
(自由浮窗手勢操作演示)
這個功能類似華為的平行視界,簡單理解就是一個應(yīng)用,兩屏顯示。比如當(dāng)你在橫屏狀態(tài)下逛淘寶的時候,你可以用屏幕的一邊去和客服聊天,另一邊則用來逛新店;再比如你在聊微信的時候,你可以一邊刷朋友圈,一邊和朋友暢聊等等。
(淘寶)
(美團(tuán))
(嗶哩嗶哩)
(微信)
不同應(yīng)用的平行視窗截圖
這也是傳統(tǒng)直板手機(jī)所不具備的優(yōu)勢。
IT之家咨詢 OPPO 客服了解到,目前 OPPO Find N 平行視窗支持釘釘、微信、QQ 郵箱、淘寶等 App,不算多,但也基本能夠滿足需求。
另外強(qiáng)調(diào)一點(diǎn),IT之家的“平行視窗”也已經(jīng)在路上了。
一些應(yīng)用未做好全屏顯示優(yōu)化,或不支持平行視窗(或關(guān)閉平行視窗),此時打開應(yīng)用之后,雖然畫面鋪滿了 OPPO Find N 整個屏幕,但畫面也是局部放大,顯示內(nèi)容甚至比不過傳統(tǒng)手機(jī)。
另外有些應(yīng)用,打開之后圖片和文字的排版會稍顯不協(xié)調(diào)。
(上面截圖可以看到,在全屏模式下,圖片多的 App 顯示內(nèi)容明顯比不過正常比例的手機(jī))
OPPO Find N 提供了“兼容模式”,你可以自行選擇應(yīng)用顯示比例,包括全屏、4:3 和 16:9。
這里以《網(wǎng)易云音樂》為例,全屏狀態(tài)下,《網(wǎng)易云音樂》頂部的 Banner 圖就占了屏幕的一半顯示面積,圖是看爽了,但下方的內(nèi)容也被遮擋了很多。選擇 16:9,雖然兩側(cè)有白邊,但此時《網(wǎng)易云音樂》已經(jīng)正常顯示,點(diǎn)擊兩側(cè)的箭頭,你還可以自由選擇《網(wǎng)易云音樂》的顯示位置。
當(dāng)然,以筆者的實(shí)際體驗(yàn)來說,絕大部分應(yīng)用的全屏體驗(yàn)都是不錯的,OPPO 的“兼容模式”,是給了用戶多一個選擇。
從“全屏應(yīng)用”延伸到游戲。在《王者榮耀》《原神》等游戲中,OPPO Find N 的大屏是不占優(yōu)勢的,雖然中心畫面會進(jìn)行放大,但游戲畫面兩側(cè)實(shí)際上是被裁切的,你同樣可以在“兼容模式”中設(shè)置 4:3 或 16:9 顯示比例。
像《王者榮耀》這樣對視野有嚴(yán)格要求的 MOBA 游戲,用全屏玩是明顯吃虧的。
不過,《和平精英》是個例外,在全屏模式下,和平精英并不是局部放大裁切,而是像超廣角一樣,有了更大的顯示視野,比如下圖,16:9 和全屏顯示模式下,全屏顯然顯示的畫面更廣闊。
(和平精英全屏后,畫面視野明顯增大)
《原神》在全屏顯示比例下,畫面雖然也是裁切放大,但好處是放大之后畫面細(xì)節(jié)更豐富了,人物的動作細(xì)節(jié)也進(jìn)一步放大。如果你想即保留一定的視野范圍,也獲得更豐富的畫面細(xì)節(jié),可以嘗試一下 4:3 顯示比例。
(原神全屏后,視野雖然縮小,但畫面細(xì)節(jié)更豐富)
總而言之,“兼容模式”給了 OPPO Find N 用戶不同的選擇,用一種另類的方式,彌補(bǔ)了“大屏無法充分利用”的這個遺憾點(diǎn)。
OPPO Find N 折疊屏手機(jī)搭載的是目前的旗艦驍龍 888 移動平臺,有 8GB +256GB,12GB+512GB 兩個內(nèi)存和存儲選項(xiàng)。IT之家拿到的是 12GB+512GB ,核心配置方面是旗艦水準(zhǔn),沒什么好說的。
關(guān)于性能部分,可以查看IT之家微信公眾號的評測文章:
《用了 OPPO Find N,才知道什么叫最好用的折疊屏》
續(xù)航額外提一筆。OPPO Find N 搭載了 4500mAh 的電池,對于這樣小尺寸的折疊屏手機(jī)來說,很不容易。
IT之家也進(jìn)行了簡單的測試,OPPO Find N 滿電的情況下,大屏狀態(tài),先在 Wi-Fi 網(wǎng)絡(luò)下玩了 30 分鐘的《王者榮耀》游戲,耗電 6%。接著又在 Wi-Fi 網(wǎng)絡(luò)下用《嗶哩嗶哩》看了 40 分鐘的 1080P 高碼率電影,耗電 3%。根據(jù)兩項(xiàng)測試結(jié)果,再結(jié)合日常使用、待機(jī)的體驗(yàn),OPPO Find N 的續(xù)航能力大大至少是超過筆者預(yù)期的。
在日常使用中,OPPO Find N 的續(xù)航是足夠滿足筆者一天正常使用的(基本全程使用大屏,早晨 8 點(diǎn)到晚上 6 點(diǎn)期間無需充電)。
通過下面不同時間、不同應(yīng)用場景的耗電截圖,基本可以了解到 OPPO Find N 的續(xù)航水平。
(筆者日常使用中的電量截圖)
至于 33W 的快充,肯定是不盡興的。在電量為 0 的情況下,30 分鐘可充到 60%,56 分鐘充滿到 100%,這個成績放在 2022 年,只能說中規(guī)中矩吧。
(OPPO Find N 充電時間表)
相機(jī)方面,OPPO Find N 有后置三攝系統(tǒng),包括 50MP 廣角主攝,IMX766 傳感器、16MP 超廣角鏡頭、13MP 2X 長焦鏡頭。
OPPO Find N 的主攝是響當(dāng)當(dāng)?shù)钠炫炈疁?zhǔn),畢竟早在一年前 OPPO 就首發(fā)了 IMX766,在接下來的 OPPO Find X3 系列上,這枚 IMX766 也被調(diào)教的極其出色,所以 OPPO Find N 的主攝影像實(shí)力,沒什么好擔(dān)心的。
體驗(yàn)部分,OPPO Find N 借助大屏的優(yōu)勢,可以實(shí)現(xiàn)照片的“即拍即預(yù)覽”功能,如下圖所示,右側(cè)屏幕拍攝,隨后樣張?jiān)谧笃琳故尽?/p>
此外,給女朋友拍照時,你還可以打開“小屏預(yù)覽”,女朋友也可以通過外屏查看拍攝狀態(tài)等。
樣張部分,主攝照片曝光充足,色彩明艷,整體很討好眼球。
放大之后,大屏上這么小的文字都能看清,可見細(xì)節(jié)解析力也是很猛的。
換一個光線對比更強(qiáng)烈的場景,下面這張照片更能看出,OPPO Find N 對色彩的呈現(xiàn)的確很明艷討喜。
而且,盡管是迎著夕陽,背光的電梯、花束依然亮度充足,細(xì)節(jié)豐富,遠(yuǎn)處的樓房也沒過曝,動態(tài)范圍表現(xiàn)很好,畫面看起來很通透。
接著是夜拍表現(xiàn),下面這張照片實(shí)拍環(huán)境是比較黑暗的,但 OPPO Find N 的直出照片呈現(xiàn)出不錯的亮度,而且畫面中只有小屋上的白布高光處出現(xiàn)了一些過曝,整體來說,寬容度表現(xiàn)很好。
使用夜景模式再拍一張,畫面整體明亮了一些,小屋上的白布高光處也被壓了下來,動態(tài)范圍更上一層樓。
下面再為大家展示一些來自 OPPO Find N 的拍照樣張,供大家參考:
(超廣角)
(主攝)
(2X)
(主攝)
(主攝)
(主攝)
(主攝夜景)
(主攝夜景)
在筆者撰寫這篇文章的時候,OPPO Find N 的全網(wǎng)預(yù)約量已經(jīng)突破 100 萬,“從嘗鮮,到常用”,單從上述數(shù)據(jù)來看,OPPO Find N 是有資格喊出的這句口號的。
作為 OPPO 的首款折疊屏產(chǎn)品,Find N 的完成度非常高的,在這幾年時間里,OPPO 沒有跟風(fēng)強(qiáng)上折疊品手機(jī),而是耐心打磨體驗(yàn),從尺寸形態(tài)到轉(zhuǎn)軸、折痕,從應(yīng)用交互的實(shí)用性再到懸停的創(chuàng)新體驗(yàn),Find N 的每一處細(xì)節(jié),都隱藏著 OPPO 多年來對折疊屏手機(jī)的觀察和思考。更何況,7699 元起的售價,OPPO Find N 注定將成為折疊屏手機(jī)普及道路上的一座里程碑。
第一,預(yù)算夠多,對折疊屏手機(jī)非常感興趣,OPPO Find N 作為日常的主力機(jī)使用是毫無問題。
第二,有直板機(jī)作為備用機(jī),想買一臺折疊屏嘗鮮的用戶,OPPO Find N,將會是你體驗(yàn)折疊屏最好的選擇。
《【IT之家開箱】OPPO Find N 折疊旗艦圖賞:無縫折疊,自由懸停》
《終于有一款好看又實(shí)用的折疊屏手機(jī)了!》
我是從今年5月份第一次接觸流馬這個平臺。第一次聽到這個名字的時候,就覺得挺有趣的,猜測其名字應(yīng)該是取自諸葛亮的“木牛流馬”,后來和作者證實(shí)了一下,確實(shí)如此。當(dāng)初諸葛亮發(fā)明木牛流馬是為了提高運(yùn)輸效率,而流馬測試平臺是為了提高測試效率,可以說這個名字取得“恰到好處”。
本文一萬兩千字左右,我寫了好多天,可能是我耗時最久的一篇文章。其實(shí)寫文章不是最難的,難的是邊學(xué)習(xí)、邊摸索、邊踩坑、邊解決問題、邊寫文章記錄、邊總結(jié)。所以寫得還算是比較用心的,整體來說也比較詳細(xì)。讀起來可能會有點(diǎn)長,大家可以先關(guān)注收藏、后期有時間、空下來了再照著文章內(nèi)容仔細(xì)研究。內(nèi)容大致分為以下四個部分:
【簡介篇】
【部署篇】
【使用篇】
【總結(jié)篇】
以下項(xiàng)目概述及功能介紹內(nèi)容來自官網(wǎng)及GitHub項(xiàng)目介紹
流馬是一款低代碼自動化測試平臺,旨在采用最簡單的架構(gòu)統(tǒng)一支持API/WebUI/AppUI的自動化測試。平臺采用低代碼設(shè)計模式,將傳統(tǒng)測試腳本以配置化實(shí)現(xiàn),從而讓代碼能力稍弱的用戶快速上手自動化測試。同時平臺也支持通過簡單的代碼編寫實(shí)現(xiàn)自定義組件,使用戶可以靈活實(shí)現(xiàn)自己的需求。
項(xiàng)目分為平臺端和引擎端,采用分布式執(zhí)行設(shè)計,可以將測試執(zhí)行的節(jié)點(diǎn)(即引擎)注冊在任意環(huán)境的任意一臺機(jī)器上,從而突破資源及網(wǎng)絡(luò)限制。同時,通過將引擎啟動在本地PC上,方便用戶快速調(diào)試測試用例,實(shí)時查看執(zhí)行過程,帶來傳統(tǒng)腳本編寫一致的便捷。
官網(wǎng):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
平臺技術(shù)棧:前端VUE+ElementUI,后臺Java+SpringBoot,測試引擎Python。
官方部署文檔地址:https://docs.qq.com/doc/p/c989fa8bf467eca1a1e0fa59b32ceab017407168,共提供了兩種部署方式,一種是容器部署,一種是常規(guī)部署。容器部署的好處是簡單、快捷,常規(guī)部署方式的好處是相對于容器來說、出現(xiàn)問題容易排查,缺點(diǎn)是步驟較為繁瑣。兩種方式各有優(yōu)劣,根據(jù)自己的喜好自由選擇即可。本文采用的是常規(guī)部署方式。
機(jī)器/系統(tǒng) | 部署環(huán)境 | 說明 |
192.168.1.123,CentOS7 | JDK8 MySQL8 Nginx | CentOS7內(nèi)網(wǎng)服務(wù)器:
|
192.168.1.131,Windows10 | Git JDK8 Maven IDEA編輯器 NodeJS | 個人Windows10辦公電腦:
|
192.168.1.188,Windows7 | Python3 Selenium Chrome ChromeDriver | 同一內(nèi)網(wǎng)下的其他Windows主機(jī):
|
關(guān)于執(zhí)行引擎機(jī),也可以繼續(xù)使用個人辦公電腦作為執(zhí)行引擎機(jī),考慮到個人電腦經(jīng)常會關(guān)機(jī)重啟,就需要來回啟動執(zhí)行引擎,比較麻煩,所以我就選了一臺本地Windows主機(jī)。當(dāng)然也可以部署在Linux系統(tǒng)上,不過對于UI自動化測試而言,沒有可視化的界面展示,調(diào)試起來相對麻煩一些。
CentOS服務(wù)器和個人Windows電腦分別需要安裝JDK。CentOS下,推薦腳本部署方式:
安裝腳本下載:https://share.weiyun.com/6JMLvSyK
JDK包下載地址:https://share.weiyun.com/mKDxXd1x
source jdk_install.sh # 通過source命令安裝,省去配置環(huán)境變量步驟
CentOS下安裝,本次通過docker進(jìn)行快速安裝,如服務(wù)器或其他內(nèi)網(wǎng)機(jī)器已安裝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
進(jìn)入mysql容器
docker exec -it mymysql sh
連接mysql
mysql -uroot -p # 登錄mysql,根據(jù)提示輸入密碼123456
進(jìn)入mysql命令行執(zhí)行:
mysql> create database liuma character set utf8 collate utf8_general_ci;
CentOS下安裝,推薦腳本部署方式
nginx安裝腳本下載地址:https://share.weiyun.com/HLuVRTO2
nginx安裝包下載地址:https://share.weiyun.com/uhffdijl
將其下載下來,上傳到服務(wù)器,執(zhí)行以下命令安裝:
source nginx_install.sh
Windows下安裝,用于拉取項(xiàng)目代碼,下載后雙擊、按照提示一步步安裝。
下載地址:https://share.weiyun.com/NJBlZGmE
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
CentOS或Windows下安裝均可,執(zhí)行機(jī)選用哪個系統(tǒng)就安裝在哪個系統(tǒng)下。如果是Linux系統(tǒng),可以參考之前的文章《Linux下一鍵安裝Python3&更改鏡像源&虛擬環(huán)境管理技巧》,如果是Windows系統(tǒng),則在Windows系統(tǒng)下安裝python3.
git clone https://github.com/Chras-fu/Liuma-platform.git # 克隆平臺代碼
git clone https://github.com/Chras-fu/Liuma-engine.git # 克隆引擎代碼
平臺代碼目錄:
進(jìn)入前端文件目錄,安裝相關(guān)依賴并執(zhí)行構(gòu)建
npm install # 安裝相關(guān)依賴
npm run build # 構(gòu)建
出現(xiàn)"Build complete."提示代表構(gòu)建成功:
構(gòu)建成功后,目錄下會生成dist文件目錄,可以將其打包成.zip格式并上傳至服務(wù)器,然后再解壓
用IDEA打開liuma-platform/LiuMa-backend,使用maven安裝依賴
文件位置:liuma-platform/LiuMa-backend/src/main/resources/application.properties,配置如下所示:
# 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
注意事項(xiàng):
文件位置:liuma-platform/LiuMa-backend/src/main/resources/application.properties,配置如下所示:
# aliyun 阿里云
# 阿里云郵件key
aliyun.email.accessKey=LTAI5tDVn8kT1avi84cFX8TT
# 阿里云郵件secret
aliyun.email.accessSecret=Dq8pm0DkZSqeMwRKOQhEid3fGPkL09
# 發(fā)送人郵箱地址
aliyun.email.runnerSenderAddress=jigang.chen@1897745962796526.onaliyun.com
aliyun.email.runnerSenderName=執(zhí)行通知機(jī)器人
文件位置: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
提示“BUILD SUCCESS”即表示打包成功,目錄下會多出一個LiuMa-1.0.3.jar的jar包(我目前拉的最新代碼,打包出來的是1.0.3,還有個LiuMa-1.0.0.jar包是兩個月前打包的)
將前端打包后的文件夾dist上傳到:nginx安裝目錄/usr/local/nginx/html/下
可以在/home目錄下新建一個文件夾liuma,用于存放前面打包的jar包文件:LiuMa-1.0.3.jar,執(zhí)行命令,后臺啟動服務(wù):
nohup java -jar LiuMa-1.0.3.jar > logs.log 2>&1 &
啟動后,可以查看logs.log日志文件,看看是否啟動成功,以及是否成功連接到數(shù)據(jù)庫,連接成功后自動創(chuàng)建相關(guān)數(shù)據(jù)表:
① 新建nginx_liuma.conf
在nginx的/usr/local/nginx/conf目錄下新建nginx_liuma.conf,nginx用于配置server的代理轉(zhuǎn)發(fā),詳細(xì)配置如下:
#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
測試過程中可能會出現(xiàn)失敗提示"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
訪問前端:http://192.168.1.122:8888/,管理員賬號:LMadmin,密碼:Liuma@123456
登錄后的頁面如下所示:
因?yàn)榱黢R是前后端分離項(xiàng)目,所以前端能訪問并不代表后端也是正常的。如果登錄遇到502,則是后臺服務(wù)器沒啟起來,多半是數(shù)據(jù)庫的問題,可以通過以下方式排查:
另外,如果前端頁面訪問不了,很可能是防火墻沒開放權(quán)限,需要在防火墻中放開上述配置文件中配置的8888端口:
firewall-cmd --permanent --add-port=8888/tcp
firewall-cmd --reload
如果是前后端服務(wù)是部署在云服務(wù)器,需要在安全組中放開8888端口。
測試引擎可以理解為接口測試和UI自動化測試的運(yùn)行環(huán)境。測試引擎可以選擇部署在Linux系統(tǒng),也可以選擇使用個人Windows電腦,最好處于同一局域網(wǎng)下。當(dāng)然如果服務(wù)端是部署在云服務(wù)上,有公網(wǎng)IP地址,Windows是個人辦公電腦也可以,只要引擎電腦能要連上部署后端服務(wù)的那臺服務(wù)器就行。以下是引擎部署過程:
前面已經(jīng)通過“git clone https://github.com/Chras-fu/Liuma-engine.git”克隆好了引擎代碼,直接上傳到對應(yīng)的服務(wù)器即可,比如我選用的是Windows作為引擎,那么直接拷貝到Windows即可。
前面依賴環(huán)境部署已經(jīng)安裝好了Python3,創(chuàng)建并激活了虛擬環(huán)境,下面直接進(jìn)入項(xiàng)目所在目錄liuma-engine,安裝依賴即可。
pip install -r requirements.txt
對照引擎機(jī)的Chrome瀏覽器版本,下載對應(yīng)驅(qū)動,存放在/browser目錄下
① 注冊引擎
流馬平臺環(huán)境中心-引擎管理-注冊引擎,輸入引擎名稱,名稱任意,自己能識別即可,如:engine-192.168.1.188,確認(rèn)后,會彈出一個提示框,復(fù)制里面的引擎code和引擎秘鑰,后面會用到。
② 配置引擎服務(wù)器
編輯liuma-engine/config目錄下的配置文件config.ini,進(jìn)行配置,幾個重要配置如下:
[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=****
python startup.py
引擎啟動成功后,即可在流馬平臺環(huán)境中心-引擎管理中查看引擎在線情況。一臺服務(wù)器可以啟動多個引擎,一般默認(rèn)有四個系統(tǒng)引擎,啟動后互不影響。
在開始創(chuàng)建接口測試之前,我們需要先做一些最基礎(chǔ)的準(zhǔn)備工作,例如:注冊一個項(xiàng)目,添加或注冊一個賬號,將新注冊的賬號添加到項(xiàng)目中。先看一下官方文檔對項(xiàng)目、角色、用戶的關(guān)系介紹:
登錄頁面注冊新賬號
注冊完成后,登錄管理員賬號,在【系統(tǒng)管理-用戶管理】中能看到注冊的用戶:
創(chuàng)建項(xiàng)目時,可以選擇新注冊的賬號作為管理員,后續(xù)此賬號登錄時即可看到此項(xiàng)目。
這個平臺的最大功能是自動化測試,而我們本次的目的就是體驗(yàn)這個平臺的自動化相關(guān)的功能好不好用,所以重點(diǎn)會從接口自動化測試及UI自動化測試著手。至于其他相關(guān)功能,官方使用手冊的內(nèi)容已經(jīng)寫得非常詳細(xì),這里就不做過多介紹。
接口測試需要先創(chuàng)建接口,在創(chuàng)建接口前需要先創(chuàng)建各個接口的執(zhí)行環(huán)境,也就是域名或URL:
① 新增域名標(biāo)識
在新增環(huán)境前,需要先新增域名標(biāo)識,否則在新增環(huán)境的時候無“域名標(biāo)識”內(nèi)容可供選擇
右上角配置中心-域名標(biāo)識-新增標(biāo)識,填入標(biāo)識名稱和標(biāo)識描述,確認(rèn)。
② 新增環(huán)境
添加好域名標(biāo)識,就可以新增環(huán)境了,添加環(huán)境的目的主要是為了后面運(yùn)行測試用例的時候是基于哪套環(huán)境,比如同一個項(xiàng)目,可能會有開發(fā)環(huán)境、測試環(huán)境、預(yù)發(fā)環(huán)境等等:
環(huán)境中心-環(huán)境管理-新增環(huán)境,輸入環(huán)境名稱、環(huán)境描述,確認(rèn)。
③ 新增域名
在剛新增的環(huán)境下新增域名,匹配類型選擇“域名標(biāo)識”,匹配標(biāo)識選擇第一步新建的域名標(biāo)識的名稱,域名填寫接口請求的URL地址。同Metersphere的環(huán)境管理類似,此處新建環(huán)境后,后面發(fā)起的接口測試請求,就是基于這個環(huán)境的URL發(fā)起。
① 創(chuàng)建模塊
既然是接口測試,就需要先創(chuàng)建接口,在新增接口前需要先創(chuàng)建各個模塊,用于分類管理各個模塊下的接口
② 新增接口
新增接口可以選擇手動新增和導(dǎo)入兩種方式,導(dǎo)入的方式支持文件導(dǎo)入、postman、swagger導(dǎo)入,此處我選擇的是手動新增,以登錄接口為例:
基礎(chǔ)信息部分就是接口地址、描述、名稱等信息,各個字段簡潔明了,不再贅述;請求參數(shù)部分主要涉及到請求頭、接口的請求體等。為了滿足不同用戶的登錄需求,我的接口請求參數(shù)是采用引用變量的形式來傳參。提到變量就不得不提到下面的公共參數(shù)。
① 流馬與Metersphere的公共參數(shù)的設(shè)計上的區(qū)別
新增公共參數(shù)的目的主要是為了后面在接口中引用,類似于全局變量。Metersphere和流馬都是基于項(xiàng)目進(jìn)行管理其下的環(huán)境、變量,最頂層是項(xiàng)目。Metersphere的公共參數(shù)是放在環(huán)境中進(jìn)行管理,它是一個環(huán)境下掛多個變量的概念,而流馬中環(huán)境則是和變量進(jìn)行分開,一個項(xiàng)目可以新增多個環(huán)境,一個項(xiàng)目可以新增多個公共參數(shù),環(huán)境和公共參數(shù)之間互不干擾。
公共組件-公共參數(shù)-自定義參數(shù)-新增自定義參數(shù),填入?yún)?shù)名稱、類型、參數(shù)值等。注意:同一項(xiàng)目下變量名稱不可重復(fù)。例如,新增一個登錄用戶名的公共參數(shù):
② 流馬公共參數(shù)引用
Metersphere對于公共參數(shù)的引用與Jmeter一致,都是采用${name}的形式,而在流馬中,則是通過{{$username}}形式進(jìn)行引用,與postman類似,但比postman多了個$符,postman是{{username}}。請求頭和請求體中都可以通過此種方式引用公共參數(shù),但是要注意參數(shù)的類型,請求頭中一般都是string類型的參數(shù)。
與Jmeter類似,流馬中內(nèi)置了函數(shù)助手,提供很多函數(shù)可供選擇
比如我的某個接口傳參中需要一些指定長度的隨機(jī)數(shù)字,那么則可以使用random_number函數(shù),引用方式見下圖標(biāo):
某些情況下,內(nèi)置函數(shù)可能無法滿足生成參數(shù)的需求,這是則可以創(chuàng)建一些自定義函數(shù)。按照官網(wǎng)文檔的介紹,平臺支持Python Faker庫的方法(畢竟執(zhí)行引擎就是Python),那么我們就可以創(chuàng)建一個Python方法來自定義生成一些參數(shù)。不過有一點(diǎn)需要注意,函數(shù)的返回值要使用sys_return(value)來返回。
① 創(chuàng)建自定義函數(shù)
例如我想生成隨機(jī)手機(jī)號,則可以通過如下方式常見:公共組件-函數(shù)管理-新增函數(shù),內(nèi)容如下:
可以看出,語法其實(shí)就是Python語法,只不過最后的返回值使用了sys_return代替。
② 引用自定義函數(shù)
添加完自定義函數(shù),就可以在接口傳參中引用,方式為:{{@function()}}
其實(shí)上述三個參數(shù):姓名、手機(jī)號、身份證號我都是通過自定義函數(shù)來生成的。最后發(fā)起請求時,通過日志可以看到生成的參數(shù)值:
有個很重要的細(xì)節(jié)需要注意,也是我在使用過程中遇到的一些小坑:
接口傳參中引用string類型的公共參數(shù)時需要加引號
定義參數(shù)時,如果是string類型變量:
舉個例子可能會直白一點(diǎn):
假如我們登錄接口需要傳入密碼參數(shù),而我們提前在公共參數(shù)中定義了這個變量password,值為e10adc3949ba59abbe56e057f20f883e,是一個string類型,如下圖所示:
假如值沒加雙引號的話,傳參的時候不會自動帶上引號(通過執(zhí)行打印結(jié)果可以看出),哪怕定義時選擇的是string類型,被測接口的服務(wù)端也會認(rèn)為它不是一個string類型
如果我們在公共參數(shù)中手動給它加上雙引號,此時執(zhí)行引擎Python那邊就會報錯JSONDecodeError:
解決辦法是在定義公共參數(shù)時不加引號,在接口中引用參數(shù)時,加上引號
此時就會識別成合法的string類型值:
添加模塊,新增用例頁面:
一條用例是由一個or多個接口組合而成,從而形成不同場景的業(yè)務(wù)流。前面接口管理中新建接口后,就可以在用例中選擇添加該接口,一次可選擇單個或多個。
斷言的類型有多種,比如某個添加用戶的接口,添加成功后返回值是{"a":"200","d":"30200"},其中a是固定的,即接口響應(yīng)碼,d的值用戶ID,是不固定的,那么這里就可以通過jsonpath提取器先提取d節(jié)點(diǎn)的值,用“整數(shù)”來進(jìn)行斷言:
如果某些接口用到了自定義的函數(shù)(內(nèi)置函數(shù)不需要導(dǎo)入)、公共參數(shù)、公共header等,則需要在用例中一一將它們選擇導(dǎo)入,否則接口中引用不會生效。很多時候,用例執(zhí)行不同都是因?yàn)闆]有導(dǎo)入這些元素導(dǎo)致:
通常,一條用例可能會包含多個接口,而接口參數(shù)之間可能會相互關(guān)聯(lián),比如B接口的入?yún)⒂玫紸接口的出參,就需要先提取A接口的出參,再在B接口中進(jìn)行引用。
① 提取返回值
與Jmeter和Metersphere一樣,提取返回值支持正則表達(dá)式和jsonpath提取兩種方式,與與Jmeter和Metersphere不同的是,流馬提取返回值時,表達(dá)式不需要加$符號:
② 引用返回值
與前面引用公共參數(shù)不同,引用返回值的{{}}內(nèi)不需要加$符號,直接填寫變量名即可:
接口管理與用例管理中的接口信息不同步
若用例中添加了接口A,則:
比如我們創(chuàng)建了一條用例,其中添加了接口A,并在用例中給接口A添加了一個請求頭參數(shù),此時,到接口管理中查看接口A則不會同步這個請求頭參數(shù);而在接口管理中添加的請求頭參數(shù)也不會同步到用例中,相當(dāng)于用例管理和接口管理做了隔離。此時就需要兩邊各修改一次接口A,或是在接口管理中修改后再重新添加到用例中。
說實(shí)話我覺得這個設(shè)計很不好用,因?yàn)樵诂F(xiàn)實(shí)使用中,會有很多測試用例用到同一個接口。舉個例子,如果我只在測試用例A中添加或更改了某個接口的請求頭,那么其他測試用例B、C、D中則需要一一更改。
起初我以為是bug,后來特地問了作者,就是這么設(shè)計的,也不是不能改,只是處理起來會很麻煩,而且很多其他平臺也都是這么設(shè)計的,后期會慢慢優(yōu)化。
此處以在測試中常見的某個業(yè)務(wù)流程場景為例,來串聯(lián)前面提到的公共參數(shù)、自定義函數(shù)、關(guān)聯(lián)參數(shù)等等,流程如下:用戶登錄->添加一個商品->獲取商品詳情->刪除商品,從添加到刪除,這樣既形成了一個小的業(yè)務(wù)流程的閉環(huán),也避免我們后期到數(shù)據(jù)庫中手動刪除數(shù)據(jù),這也是現(xiàn)在接口流程測試中一種較為常見的做法。
一個完善的業(yè)務(wù)流程的測試用例,通常需要做以下工作:
分別看下各個接口的執(zhí)行結(jié)果,并做一些簡單的解讀,看其是否符合最初的流程設(shè)計:
① 登錄接口
賬號登錄成功,并獲取到返回值,返回賬號的user id及token信息。
② 新增商品
新增商品成功,返回d節(jié)點(diǎn)為商品的ID。
接口斷言返回值的d節(jié)點(diǎn)為整數(shù),斷言成功。關(guān)聯(lián)參數(shù)會提取d節(jié)點(diǎn)的值,作為后面接口的入?yún)ⅰ?/p>
③ 獲取商品詳情
上一個接口提取的商品ID,已經(jīng)傳入請求體,并獲取到了商品詳情。
接口斷言返回值的d節(jié)點(diǎn)的aa節(jié)點(diǎn)與商品ID變量數(shù)字相等,斷言成功。
④ 刪除商品
此處接口傳參使用的也是新增商品返回的商品ID作為入?yún)ⅲ瑒h除成功d節(jié)點(diǎn)返回值為1
接口斷言返回值的d節(jié)點(diǎn)數(shù)字恒等于1,斷言成功
web自動化測試我研究得確實(shí)不多,我想它的設(shè)計理念應(yīng)該是和接口測試類似的,比如:
以百度首頁為例,添加百度首頁的一些元素,如:搜索框、百度一下按鈕。定位方式支持selenium的八大元素定位方式
表達(dá)式直接填寫元素屬性值,比如ID定位,搜索框的ID屬性值是kw
如果選擇name定位,表達(dá)式就填wd
元素列表管理所有元素,建議不同頁面可以通過不同模塊來進(jìn)行管理,這也符合UI自動化PO設(shè)計模式中一個很重要的設(shè)計原則:同一個頁面,只管理本頁面下的頁面元素對象。
新增操作基本上涵蓋了UI自動化測試中所有可能用到的操作,比如:瀏覽器最大化、斷言、IF...ELSE、切換frame等
這里有個小點(diǎn)需要特別注意,按照我原本編寫測試腳本的固化思維是:先聲明元素對象>>再附加元素動作,比如點(diǎn)擊、雙擊、滑動、長按等,所以也想當(dāng)然地先來添加元素,結(jié)果摸索了半天沒找到入口。但其實(shí)是先選擇操作的動作,如輸入、單擊>>再選擇要操作的事先錄入好的元素:
當(dāng)然在操作設(shè)置頁面、勾選元素后面的按鈕后,也可以新建頁面元素對象:
此處以百度搜索作為一個小小的測試場景,來串聯(lián)前面提到的元素定位、添加元素等,場景流程如下:
打開瀏覽器>>打開百度首頁>>最大化瀏覽器窗口>>輸入框輸入“流馬”>>提交搜索>>斷言頁面標(biāo)題包含“流馬”>>等待三秒>>關(guān)閉瀏覽器
測試計劃作用是確定測試執(zhí)行的全部用例,以測試集合為維度管理。此外測試計劃支持定時任務(wù)和周期執(zhí)行。同時測試計劃按照版本管理,也支持集成到研發(fā)流水線。
測試集合可以看作是多個測試用例的集合,每條用例相互獨(dú)立、互不影響。填寫集合相關(guān)信息,注意版本要在配置中心提前新建好。
添加用例,可以選擇到之前創(chuàng)建的各個測試用例,API用例和UI用例可以同時選擇,按照順序混合執(zhí)行。
創(chuàng)建完的集合,可以手動執(zhí)行,也可以創(chuàng)建測試計劃定期或周期性執(zhí)行
手動執(zhí)行測試集合,生成測試報告
填寫名稱、選擇版本、執(zhí)行引擎、設(shè)置執(zhí)行時間
執(zhí)行頻率有多種方式可供選擇,類似于Jenkins或是Linux crontab的定時任務(wù):
測試計劃需要選擇測試集合,前面新建的集合在這里會選擇到,一個測試計劃可以包含多個測試集合
在使用中我也遇到了一些麻煩,有的是自己摸索解決的,有的是靠用戶手冊解決,有的則是在用戶交流群中咨詢解決的,我想肯定有人和我遇到同樣的問題或是使用感受。以下是我總結(jié)出的一些優(yōu)化建議,僅代表個人:
目前用例管理中支持用例復(fù)用,也就是復(fù)制的功能,但接口管理不支持,如果當(dāng)前有一些接口,內(nèi)容都比較相似、僅僅修改接口地址和個別參數(shù)就可以使用,那么增加這個功能就顯得很有必要。
這個也是我在使用過程中遇到的問題,比如我從A接口提取了返回值user_id需要傳到下一個B接口的請求頭中,提取的user_id值是一個int類型,而傳到B接口的請求頭中需要string類型:
① 如果通過{{user_id}}引用提取的變量值的話,B接口請求時就會報類型錯誤;
② 如果通過'{{user_id}}'引用提取的變量值的話,B接口請求時就會報錯502;
目前作者給的解決方案是在前置腳本里處理,或是寫個自定義轉(zhuǎn)換的函數(shù)
如果能在編輯用例---添加請求頭的時候直接選擇類型就好了,類似于編輯接口管理下這樣:
目前標(biāo)題只有一級“首頁”支持跳轉(zhuǎn),二級、三級不支持超鏈接,如果當(dāng)前頁面處于一個很深的層級,那么標(biāo)題跳轉(zhuǎn)顯然會比瀏覽器的后退、前進(jìn)更加自由靈活。
目前刷新頁面后,側(cè)邊欄會自動收縮,建議可以參考Metersphere以及微信聊天窗口等類似的做法,加一個固定按鈕,可以固定/取消固定側(cè)邊欄。
目前每次執(zhí)行都需要選擇一次執(zhí)行引擎,次數(shù)多了操作起來就會比較麻煩。建議可以設(shè)置默認(rèn)執(zhí)行引擎或修改執(zhí)行引擎列表順序。
點(diǎn)擊模塊名稱會查詢當(dāng)前模塊下的接口,而此時處于某個模塊下、進(jìn)入新增接口頁面時,仍需選擇一次所屬模塊,建議可以增加自動填充模塊分類功能。
假如我正在編輯某個彈框,且編輯了很多內(nèi)容,此時如果一不小心鼠標(biāo)點(diǎn)到了其他空白處,彈框就是自動消失,原本編輯的字段也需要再重新編輯。如果點(diǎn)擊其他空白處,可以彈出一個二次確認(rèn)彈框,會避免很多誤操作。
以上這些都是我親自使用過程中的總結(jié)體會。所謂“實(shí)踐是檢驗(yàn)真理的唯一標(biāo)準(zhǔn)”,一個工具/平臺好不好用,不是靠聽別人說的,而是要自己試了才知道。
正如前面項(xiàng)目概述提到的“項(xiàng)目分為平臺端和引擎端,采用分布式執(zhí)行設(shè)計,可以將測試執(zhí)行的節(jié)點(diǎn)(即引擎)注冊在任意環(huán)境的任意一臺機(jī)器上,從而突破資源及網(wǎng)絡(luò)限制。同時,通過將引擎啟動在本地PC上,方便用戶快速調(diào)試測試用例,實(shí)時查看執(zhí)行過程,帶來傳統(tǒng)腳本編寫一致的便捷。”
也就是說執(zhí)行引擎和前后臺服務(wù)是獨(dú)立開來的,執(zhí)行引擎既可以部署在Linux,也可以部署在Windows,也可以使用個人辦公電腦,從而快速調(diào)試。
另外一個巧妙的地方我覺得沒有那么多套路,基本上上手一遍就能摸索出規(guī)律,例如前面提到的:一條用例包含多個接口,相應(yīng)的就能想到計劃包含集合、集合包含用例、用例包含接口或元素對象。
支持接口測試、WEB測試、APP測試,支持定時任務(wù)、周期性執(zhí)行、并發(fā)執(zhí)行
平臺技術(shù)棧:前端VUE+ElementUI,后臺Java+SpringBoot,測試引擎Python,支持Python自定義函數(shù),相對了解Python編碼的測試工程師來說較為友好,使用起來會更靈活。
部分細(xì)節(jié)功能不完善、或者說不好用。比如前面提到的優(yōu)化建議,以及一些注意事項(xiàng),都是我在使用過程中遇到并總結(jié)的。
流馬的定位是低代碼測試平臺,旨在幫助不懂代碼的測試工程師也可以自由地開展多種類型的自動化測試。我自認(rèn)為稍微懂一點(diǎn)點(diǎn)代碼,也見識過一些開源平臺,但在使用過程中,確實(shí)也摸索了幾天。注意,這里的上手指的是開展公司的實(shí)際測試業(yè)務(wù),而不是請求一個百度接口或是打開一個百度頁面這種demo這么簡單,要能把公司的業(yè)務(wù)遷移到平臺并成功運(yùn)行起來,這意味著肯定要花費(fèi)一定的時間學(xué)習(xí)和摸索、以及解決使用過程中遇到的問題。
用戶手冊的內(nèi)容相較于Metersphere確實(shí)不夠詳細(xì),很多都是一個簡短的描述,沒有具體用法示例,這也就造成了遇到一些問題時可參考的內(nèi)容較少。不過這也能理解,畢竟MS背后是商業(yè)化的公司,有充足的人力可以維護(hù)和更新文檔,而流馬據(jù)我所知只有作者一人維護(hù)。
由于篇幅、個人時間以及能力限制,只羅列了上述有限的功能和使用細(xì)節(jié),更多精彩功能還需大家親自部署體驗(yàn)。按照慣例,簡單對流馬做個評分總結(jié),評分過程中可能稍帶有主觀色彩,畢竟我也是用戶,但會盡量本著客觀公眾的原則。評測還是基于之前預(yù)告篇中的維度。
特別聲明:由于每個人的關(guān)注點(diǎn)不一樣,所以評判標(biāo)準(zhǔn)可能也會有所偏差。
測評維度 | 詳細(xì)說明 | 評分(星級越高,得分越高) |
環(huán)境搭建 | 1.依賴環(huán)境:較多,支持容器化部署,傳統(tǒng)部署相對較繁瑣些 2.搭建難度(難度越大、星級越低):對新手來說難度會較大,因?yàn)樯婕暗墓ぞ吆头?wù)比較多 | ☆☆☆ |
用例管理 | 1.是否支持導(dǎo)入用例:支持多種平臺及格式導(dǎo)入 2.用例執(zhí)行順序編排:支持,可以拖動 | ☆☆☆☆☆ |
接口測試 | 1.單接口測試:支持,不過沒看到導(dǎo)入CSV入口,參數(shù)化和數(shù)據(jù)驅(qū)動支持情況不詳 2.接口流程測試:支持,多種參數(shù)提取方式,支持測試集合、測試計劃,可以定期或周期性執(zhí)行 3.自動生成測試報告:支持,簡潔 | ☆☆☆☆☆ |
UI自動化測試 | 1.APP:支持 2.Web:支持 | ☆☆☆☆☆ |
性能測試 | 不支持 | 無 |
擴(kuò)展功能 | 1.是否支持二開:支持 2.是否支持定時任務(wù):支持 3.是否支持接入CICD:支持 4.是否支持測試結(jié)果度量:支持 5.用戶權(quán)限配置:支持,不同用戶不同權(quán)限 6.測試管理:不支持,平臺定位不是如此 7.缺陷跟蹤:不支持,平臺定位不是如此 | ☆☆☆☆☆ |
其他 | 1.文檔支持(部署教程、操作手冊):不夠詳細(xì) 2.代碼更新維護(hù)頻率:長期維護(hù) 3.社區(qū)活躍度:中等 4.易用性:上手成本略高 5.穩(wěn)定性:目前暫未發(fā)現(xiàn)bug | ☆☆☆☆ |
最后總結(jié):流馬功能強(qiáng)大,支持多種類型的自動化測試,可以滿足各種自動化測試需求;平臺定位低代碼、易使用,能夠幫助沒有代碼基礎(chǔ)的測試工程師也能快速開展自動化測試,不過平臺使用過程需要一定的學(xué)習(xí)和摸索成本,部分細(xì)節(jié)功能還需優(yōu)化完善。作為個人開發(fā)者開發(fā)的流馬平臺,能做到現(xiàn)在這樣的效果,確實(shí)非常厲害,值得點(diǎn)贊和學(xué)習(xí)!任何一個開源項(xiàng)目,既需要接受用戶的批評、質(zhì)疑、意見建議,也需要用戶的包容、鼓勵和支持,有了一定的用戶基礎(chǔ),大家群策群力,項(xiàng)目才會越來越好,帶來更多價值!
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。