SCMLife.com

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 4103|回复: 1

[推荐] IBM Rational Quality Manager 与 Selenium 的集成应用

[复制链接]
发表于 2012-12-2 14:45:04 | 显示全部楼层 |阅读模式
本帖最后由 技术狂人 于 2012-12-2 14:48 编辑
8 T% H9 W$ r5 [0 B7 s& G- l$ d: ]
9 ^9 f' O, B$ u, u# y- s
一、RQM 及其如何管理自动化测试脚本的简介
IBM Rational Quality Manager(RQM)是一款基于 Web 的出色的质量管理软件,用于贯穿软件生命周期的综合测试规划和测试资源管理。它提供了多种适配器与其他工具集成,使 RQM 能够管理并运行由其他工具创建的自动化测试脚本。
  ?' {' N. l2 _; ]Selenium 是一款基于 Web 应用的开源测试工具,它能够支持多种浏览器和多种编程语言,同时它提供了快速、轻量级的浏览器模拟器,为用户提供了最优秀框架的最佳途径。它的诸多优势,令 Selenium 成为当下非常流行的 Web 应用程序的自动化测试工具。
8 V, ?. q+ p- ]% m* eRQM4.0 版本中,提供了 JUnit Selenium Adapter 来实施与 Selenium 的集成,使 RQM 可以运行 Selenium 2.0 WebDriver JUnit4 的测试件。
/ M1 C1 F% x' ?- m- H当 JUnit Selenium Adapter 运行时,该 Adapter 会对 RQM 服务器进行轮询,以获取运行 Selenium 测试的请求。请求中包括要运行的 Java 类(例如,JUnit 测试套件或测试用例)、必需的任何其他类路径值以及要为用于运行测试的 Java 虚拟机 (JVM) 设置的任何 Java 系统属性(可选)。运行测试后,Adapter 会将执行结果以及关联的附件上传到服务器。
7 {( W! F$ v) v1 W* d/ {& s/ J
9 d* G% D, |: e' z0 o: F

6 g: a* x' v4 x$ @
二、如何配置 JUnit Selenium Adapter
在配置和使用 JUnit Selenium Adapter 之前,用于运行 JUnit Selenium Adapter 的计算机上必须有 Java 运行时环境 (JRE) 。
$ X9 e6 L1 s2 D8 b& D2 G
  • 在运行 JUnit Selenium Adapter 的计算机上,需要下载最新版本的 Selenium 客户机 Java 驱动程序,并解压到某个本地目录中。
  • 当安装 RQM 时,运行此 Adapter 所需要的组件即被放置在 RQM 安装目录中的归档文件中 (QM_install_dir/JazzTeamServer/server/conf/qm/adapters/RQMJUnitSeleniumAdapter.zip)。将此文件复制到运行 JUnit Selenium Adapter 的机器,并将此文件解压缩到本地目录。
  • 进入步骤 2 解压的文件目录,打开 <...>/RQM-Extras-JUnitSeleniumAdapter/selenium.properties 文件,将从 Selenium 客户机驱动程序下载的所有 .jar 文件添加到 com.ibm.rqm.selenium.seleniumClasspath 属性的值中。路径条目至少要包含运行 Selenium V2.0 WebDriver JUnit4 测试套件或测试用例所必需的类。使用者还可以指定其他共享库的类的路径条目来引用。例如,如果您使用的是 Selenium V 2.21.0 和 JUnit4.10,那么 com.ibm.rqm.selenium.seleniumClasspath 属性类似于以下示例:
    # o, l9 l' P( @& a+ j- B
    com.ibm.rqm.selenium.seleniumClasspath=D:/libs/selenium-2.21.0/selenium-java-2.21.0.jar;
    ( n+ G& {& j1 [/ ]( _$ VD:/libs/selenium-2.21.0/selenium-server-standalone-2.21.0.jar; ' j8 K, `+ w) d& y
    D:/libs/selenium-2.21.0/libs/apache-mime4j-0.6.jar;
      q# S! I2 A; l0 o$ {D:/libs/selenium-2.21.0/libs/bsh-1.3.0.jar;
    2 g* ], w# H7 @4 |D:/libs/selenium-2.21.0/libs/cglib-nodep-2.1_3.jar; + B0 V, o0 P% k1 b+ G3 D  T6 a) ?8 c
    D:/libs/selenium-2.21.0/libs/commons-codec-1.6.jar;
    1 M0 |8 z7 Q, m- ^3 f6 ~- w" }D:/libs/selenium-2.21.0/libs/commons-collections-3.2.1.jar;
    ; J, _- \" K  O6 N* g2 @D:/libs/selenium-2.21.0/libs/commons-exec-1.1.jar;
    ) ^% J2 a4 g2 x/ H+ E! O) U5 sD:/libs/selenium-2.21.0/libs/commons-io-2.0.1.jar;
      ]. k4 O7 f" G4 Z* _# `D:/libs/selenium-2.21.0/libs/commons-jxpath-1.3.jar;
    - s+ q! z$ M3 q  D8 V- j0 g, zD:/libs/selenium-2.21.0/libs/commons-lang-2.6.jar;   U8 v" a/ A, c; x$ [) |
    D:/libs/selenium-2.21.0/libs/commons-logging-1.1.1.jar; 1 Q& F- v1 b$ X/ k4 J9 N$ B3 k- }
    D:/libs/selenium-2.21.0/libs/cssparser-0.9.5.jar;
    + N1 E5 G5 p" x1 z4 I- W' B, |D:/libs/selenium-2.21.0/libs/guava-11.0.1.jar;
    & S! c. k- h0 t5 CD:/libs/selenium-2.21.0/libs/hamcrest-core-1.1.jar;
    ! e. k2 A9 j7 g0 a8 ]6 W4 xD:/libs/selenium-2.21.0/libs/hamcrest-library-1.1.jar;
    2 I$ d/ f$ f$ V  W. a1 r% ~D:/libs/selenium-2.21.0/libs/htmlunit-2.9.jar; + Y" q* ?/ x+ z6 E+ r
    D:/libs/selenium-2.21.0/libs/htmlunit-core-js-2.9.jar;
    , ^0 y# T; x0 O  q- A: C2 N- B6 @2 uD:/libs/selenium-2.21.0/libs/httpclient-4.1.3.jar;
    5 g" |% Q, x2 q, fD:/libs/selenium-2.21.0/libs/httpcore-4.1.3.jar;
    . _2 ^: g7 @/ f, }D:/libs/selenium-2.21.0/libs/httpmime-4.1.3.jar; 9 o. H6 q) ?  I+ C( v& N
    D:/libs/selenium-2.21.0/libs/ini4j-0.5.2.jar; - l1 E" ?0 {$ j  X4 m
    D:/libs/selenium-2.21.0/libs/jcommander-1.13.jar;
    + p& ~3 S" j% s* e. r0 |D:/libs/selenium-2.21.0/libs/jna-3.4.0.jar;
    % K. @3 Z1 _' S- a  S+ c+ dD:/libs/selenium-2.21.0/libs/jna-platform-3.4.0.jar; : k2 U2 R  W( ^; P# k- x/ a4 n8 N
    D:/libs/selenium-2.21.0/libs/json-20080701.jar;
    + w/ p( N; O4 A7 o8 j! V1 fD:/libs/selenium-2.21.0/libs/junit-dep-4.10.jar;
    ' y7 |6 N. P- Q) |" rD:/libs/selenium-2.21.0/libs/nekohtml-1.9.15.jar;
    , N* E" T4 b  c) _2 `) l: YD:/libs/selenium-2.21.0/libs/operadriver-v0.11.jar; / Y) a% N! }/ y
    D:/libs/selenium-2.21.0/libs/protobuf-java-2.4.1.jar; 8 I; [! `1 b% c. b0 t
    D:/libs/selenium-2.21.0/libs/sac-1.3.jar; * }8 f9 }* A3 q2 {
    D:/libs/selenium-2.21.0/libs/serializer-2.7.1.jar; 8 h6 i% v  k4 x* i6 y2 I
    D:/libs/selenium-2.21.0/libs/testng-6.0.1-nobsh-noguice.jar; ; ^+ [3 F& ^7 k
    D:/libs/selenium-2.21.0/libs/webbit-0.4.6-full.jar; ( ?9 A& j/ A) l. `
    D:/libs/selenium-2.21.0/libs/xalan-2.7.1.jar;
    ' W5 }$ N0 m) A3 Y6 UD:/libs/selenium-2.21.0/libs/xercesImpl-2.9.1.jar; * |) p$ t3 V( ~9 d- k7 a  H% p
    D:/libs/selenium-2.21.0/libs/xml-apis-1.3.04.jar;
    2 ]8 J& l9 R- xD:/libs/junit4.10/junit-4.10.jar;
    - F" b4 P) F! ?5 i% f8 ]


" }3 @% ]# o) H9 g" Z8 M; c7 L7 }4 Q& @' v. C, N
三、如何启动 JUnit Selenium Adapter
为了利用 RQM 管理并运行 Selenium 测试脚本,在配置好 JUnit Selenium Adapter 之后,可以通过命令提示符启动该适配器:
6 M& j' J+ V0 X! m' T7 M
  • 打开命令提示符,进入 JUnit Selenium Adapter 的目录
  • 根据您的操作系统,选择以下任意一种方式:/ V$ p" ^$ a  E: K; X  R
    • Windows:
      6 r. x8 o8 u8 b8 ]4 k- j
C:start.bat -repository https://qmserver:port/qm -user userid -password password [-adapterName adapter-name] [-projectArea project area] [-sleepTime sleep time] [-configFile configuration file]* b  {- G3 W1 Z) B% ~! S2 b

    % Z5 Q; t2 o; |  ?7 G
    " Q9 }( h. B- w, U6 d) Y9 \! ~5 X2 S& h2 K
    • Linux:
      ( K( E1 Q: |/ B  o: r8 e% @
$ start.sh -repository https://qmserver:port/qm -user userid -password password [-adapterName adapter-name] [-projectArea project area] [-sleepTime sleep time] [-configFile configuration file]# I0 l& [7 E5 U9 g! a$ W: u* _
其中:
/ Q! _) l5 A# |" y8 k& l
  • qmserver 是质量管理服务器的主机名或 IP 地址。
  • port 是质量管理服务器运行于的端口。
  • userid 是具有运行适配器的许可证的质量管理的注册用户标识。
  • password 是所提交的用户标识的密码。
  • adapter name 是用户指定的适配器名称。
  • project area 是已登录的项目的名称。
  • sleep time 是两次轮询任务之间的轮询时间间隔。缺省设置是 5 秒钟。
  • configuration file 是用于存储和读取此适配器设置的文件。缺省文件名为 config.ini。( {9 b& m# j1 {) u4 G
当成功启动该适配器时,将看到如下提示:) ^. P( [; c7 @  M) a0 c, H

- T# v( a* O3 H: C' Y) I/ e图 1. 启动 JUnit Selenium Adapter; h. H7 y+ a* b( r4 h
+ V' N: _4 O8 f9 _- d8 O
该适配器会生成一个配置文件(config.ini 文件或 -configFile 选项中所指定的文件)以及包含相关的注册信息。当适配器重新启动时,会复用此信息。+ A( t/ C) A  @
因此,若下次要从 config.ini 文件重新启动 JUnit Selenium Adapter,可以不用添加参数直接运行,如 start.bat。" f8 w' j6 x# h: y7 H$ {) L# o

3 X6 T3 D- c( W9 |2 ]& N. d
! ]) h# R6 H4 U4 ]
四、在 RQM 上管理并运行现有的 Selenium V2.0 WebDriver Junit4 测试脚本
2 O9 G3 ?5 y( d7 K
Selenium 脚本示例" H! g, ~7 v% i: O9 B% d6 E
public class DemoTestCase {
" _3 q+ F6 J4 t9 N! F% `0 K private WebDriver driver;
5 Z" `. {" p2 G6 Z+ m, | private String baseUrl;
4 j* H  W7 a5 t$ Y  k* t private StringBuffer verificationErrors = new StringBuffer();
! P4 t1 c6 `) y) r! M8 _. q; ~6 A6 i/ ^, W( q
@Before
% _- D7 l' F2 U6 J" |: @ public void setUp() throws Exception {7 V  I$ L6 B( i" M. f2 N2 W" ]2 ?
driver = new FirefoxDriver();
- g7 p1 D% h  c( m) G' N baseUrl = "http://www.baidu.com";
6 L8 u4 Z" }: \1 T5 s& A( ^% k }
# P0 ?) }' u/ |" V( E# \2 `' ~- K6 S
@After
% _, ~* \- |6 U- g( K public void tearDown() throws Exception {
9 r9 [7 ?" ^8 E; a  w8 x driver.quit();1 X6 M8 \  g- |, n) F5 I7 X
String verificationErrorString = verificationErrors.toString();
: @7 I4 u- f3 a' T+ ^' y: W if (!"".equals(verificationErrorString)) {
1 S: [- m. Z! G" b' T2 ]: |2 m fail(verificationErrorString);2 _1 ~3 T9 P8 K: S. D0 p6 |
}- F, r3 k# [" q2 o
}
/ i+ c+ Z8 S" N1 }  _* h2 U2 L
4 o- C) N4 m: v4 F) M5 H% M @Test. v0 J, w3 s; p$ {# F3 j8 V
public void test() throws Exception {
6 @, P6 l( O2 e& C driver.get(baseUrl);! O& M: C0 m4 }+ m4 V, x- U! j4 s
WebElement element = driver.findElement(By.id("kw"));5 K; [  [: Q" n
element.sendKeys("seleniumhq");
) L% W* A) C; n8 N( U* J element.submit();
) r0 }! t% {6 E5 `9 J9 X System.out.println("Driver:" + driver.getTitle());
, ~5 @% e5 L9 `5 K$ W; {) l) { }
$ w: j4 }& Q- t) F. X+ k- O3 q0 v}
; U" s: T& h( G, s: |: ?
接下来将演示如何在 RQM 中管理并运行现有的 Selenium V2.0 WebDriver Junit4 测试脚本。! h! M: c! E- C
  • 打开登录 RQM 用户界面,进入 Project Area,通过菜单 Construction >> Create Test Case 创建一个 Demo Test Case.& I; S7 E4 Q) @" p
$ v; O% O7 r! o' A
图 2. 创建 Test Case1 \4 [2 K( G8 t1 b. @
; R  F; B: J9 B- Z- w
  • 通过菜单进入 Construction >> Create Test Script,填写对应的 Selenium 脚本的信息。注意以下关键字段值的填写:
    - Y# a( ^. ~/ O
    • Type:选择 JUnit Selenium 作为脚本类型。
    • Test Class: 要执行的 JUnit Selenium 类的名称。
    • Classpath: 运行测试类所需要的类路径条目,以分号分隔。
    • Java System Properties: 要传递给 JVM 的 Java 系统属性。4 A$ V& J  D' \, o& p) f% {7 X

    6 @7 l$ S+ f! r; k1 W& Y2 |% n
& G( \' P5 ]% y# [5 V) Q
图 3. 创建 Test Script
/ l4 H) H0 P) j3 | # T' i1 E& g5 I7 f/ D
  • 将 Test Case 与 Test Script 相关联:% k2 @% [6 f, W3 ~2 A
进入步骤 1 创建的 Test Case,加载 Test Script 模块,点击 Add Test Script,选择步骤 2 创建的 Test Script。8 S* A: g4 f& Z1 {: A2 \/ d
点击确认,将选中的 Test Script 加入到当前 Test Case 中,并保存。) Z3 {  d9 [$ e) O1 l
3 G' {* i; v2 l3 `
图 4. 关联 Test Case 与 Test Script" P( m; W% ~; h/ w# }
. L3 F! k/ Q* E5 F2 c
  • 创建 Test Case Execution Records (ER):
      {( S1 n$ x8 z6 ]
    • 自动生成 ER:若未手动创建 ER,在 run case 之后,RQM 会默认创建相应的 ER。1 X# G3 k$ ^2 ^, n" X, m: K' U' o
    • 手动创建 ER:在 Test Case 页,加载 ER 模块,点击 Generate Test Case Execution Records 图标,输入测试环境的信息即可创建。然后确认运行环境信息,并保存 ER。
        O" N7 X7 R' U& U3 T
    , D; y) h, P) Z* u% }
1 d, O. p( ~4 y: t
图 5. 手动创建 ER
/ _6 M" B8 B1 ? 6 J/ i0 Z. H% W8 E* F% I
  • 运行脚本:3 h4 y* l* T. \# l* g3 S9 F
    • 前置条件:运行的目标计算机上的 Adapter 是启动着的。
    • 方式一:在 ER 模块中,选中相应运行环境的 ER,点击 Run Test。
      / a( ^2 ]! G0 v7 W5 I

    * [: M' x# I& u: \8 r9 O
0 b  K4 N7 N) i# c( ]
图 6. 选择特定的 ER 记录运行脚本! E! F$ D; R* L2 P" v) c& I

0 c0 O8 G: N8 H

    - [6 ?. p1 W# y# x% ~( K* m( y" `$ \* w3 ~

    ; d* P/ |2 K, B% h' c& p% _9 [4 s$ W/ O3 A
    • 方式二:通过 Test Case 头尾的图标直接调出 Run Test Case 的配置页面。
      ( y+ r$ I+ b% L, h9 n- Y
! {* n! L. D; [2 f5 g
图 7. Run Test Case 的图标所在位置
7 Z* j1 x, P( u* l* ]0 a* e, P
4 `* R2 R* k; h5 p
' l# h  j: r7 L1 h# ~1 T图 8. Run Test Case 的配置页面
! f$ l  W! R$ V) j) _ ! t. c8 g; {6 \3 P8 J
  • 运行过程:
    6 _2 q4 _; N* t& \

9 T, I' _. J+ u+ p图 9. Test Case 运行时界面
; o: g; O5 T$ y0 `1 Q & E8 A6 P7 p+ I; U
# L  c* o4 S4 f: q) S
图 10. Test Case 运行结束界面
, o0 j3 v4 K) R8 y3 C* q . y' r* w/ C/ e, q
  • 运行后相应的 ER 状态会同步更新。5 f9 A* }. Y2 e
( a/ h( x! y/ F; B- @  `  p) J
图 11. 运行成功的 ER 状态- O1 q. \- t. h1 u7 d5 N

7 u& S3 `1 \# L$ W# s: ]" w- T

/ l" p+ D( q" `& p3 ~6 T
5 N5 j! r- {" [& T* ]# e
五、测试结果和测试报告
运行 Selenium 测试后,RQM 同时提供了相当不错的测试报告。您可以查看执行结果来获取 JUnit 测试的详细信息:# v* j) [! E, ]4 W- P
  • JUnit 测试名称
  • 测试的启动和停止次数
  • 成功 / 失败状态,对于失败的测试,将提供导致失败的异常。
  • 由测试生成的屏幕捕获 ( 可选 )
      P9 ~. ?2 w* v' m
上一章节的示例,运行成功的结果,如图所示:
5 `  l+ l0 [2 a8 ~& I. k
. ~/ k9 Z# B) S5 [$ T图 12. 无屏幕捕获的 Test Case 运行结果报告
& S- O7 \, ^2 W7 h
( N4 g( F' \. u5 @6 j# l" R2 S由于 Selenium 脚本通常会适当地针对浏览器会话屏幕进行屏幕捕获,以便作为测试结果输出,同时也方便排查错误。因此在通过 RQM JUnit Selenium Adapter 运行 Selenium 脚本时,也考虑到了这一点。只要在代码中做一点简单的改动,便可自动将由 JUnit Selenium 测试创建的屏幕捕获添加至测试用例的执行结果中,以供日后查看。" g7 n" W# t* P8 F1 ~5 q' ^  U
在 JUnit Selenium Adapter 执行测试时,它会设置运行 JUnit Selenium 测试的 JVM 中名为"selenium.screenshot.dir"的 Java 系统属性。此 Java 系统属性的值是运行该适配器的机器上的某个目录的完整路径。在每个 JUnit Selenium 测试执行结束时,将搜索由"selenium.screenshot.dir"指定的目录以查找图像文件(.png、.jpg、.jpeg、.gif、.tif 和 .bmp)。如果找到任何图像文件,那么会在 RQM 服务器上创建文件附件,并将对这些文件附件的引用包括在执行结果中。
9 `% O. J0 T# n- h+ D7 U& |% x修改上一部分中的示例代码:# V( v5 I$ n: S+ H5 Y( h
public class DemoTestCase {
0 Z  }2 f- q4 z7 c. e. g5 B        private WebDriver driver;2 A$ [9 }- _! C! R% e- ~
        private String baseUrl;- k2 C, d+ u: T
        private StringBuffer verificationErrors = new StringBuffer();1 |$ u% K" D* S/ W
) w* ]" r3 u" K; \, S: j( k
        @Before        # |/ @3 U* t' m8 T# p" Y
        public void setUp() throws Exception {) [% n! }0 Z" w: X) n& C
                driver = new FirefoxDriver();# i7 {" o: `+ I/ ]8 ]0 j
                baseUrl = "http://www.baidu.com";& x# t: r, h, c8 E
        }
8 J0 F* x2 S& @  t5 c3 T7 s+ f! \
- X: ?! l. [- n& _2 t        @After# v0 w* Z5 `, `2 W
        public void tearDown() throws Exception {
, r6 g& [3 C: ?0 F                driver.quit();
" A3 A& F7 s! w. W2 R                String verificationErrorString = verificationErrors.toString();
3 j0 r9 Y2 T" P2 p9 {* ]. ~+ a                if (!"".equals(verificationErrorString)) {
' v, p' i5 u, Y) [5 O                        fail(verificationErrorString);
5 ]/ {/ j, i, d3 L7 ^/ c5 e                }1 ^2 I4 G" A3 S7 G8 a
        }6 ]7 ~- Y. j& s) E- H, p* W" x" o
) t  X1 l( \9 y4 A
        @Test
3 V' q/ {  \( W4 N! [        public void test() throws Exception {/ W" W* g5 F/ X4 @, u' `
                driver.get(baseUrl);
2 K$ k# b! L# w7 ~% B1 k6 D: s# n                WebElement element = driver.findElement(By.id("kw"));: c& E1 P& Y% f( X9 ~
                element.sendKeys("seleniumhq");
; x" S0 s! F) S0 R" ~                element.submit();! z1 p: B' H1 x6 x7 R0 P8 I
                takeScreenShot("searchresult1.png");
/ l6 ?: K  c( a* T                System.out.println("Driver:" + driver.getTitle());               
. _, Z) C" Q/ G        }
3 u% }  L9 O$ x% q3 }       
% `  Y& D; b$ Z) c        private void takeScreenShot(String fname) throws Exception {
, m$ H3 E* I$ z0 o+ g* @* e         File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
6 s( n: S2 g0 @9 B' A2 H- h3 r& M         String imageFileDir = System.getProperty("selenium.screenshot.dir");
- f! p( J2 }/ O4 }6 Q* m, {# [% C         if (imageFileDir == null)
  S% x1 I5 n& ~0 H                 imageFileDir = System.getProperty("java.io.tmpdir");
( U+ Z8 l$ M' p8 ~+ g7 X/ B          FileUtils.copyFile(scrFile, new File(imageFileDir, fname));* Z, f7 W  K9 P. H# }" }+ t
        }
" Z( O/ H% [# q5 N( ^6 g        8 p, ?: K- {8 F: e$ H- l
}
$ V1 k& @7 u: O2 g
修改代码后,重新执行 Test Case,结果如下:
5 [( L- a0 s+ v8 }
  r& Q% X% i8 A8 |, V图 13. 保存了屏幕捕获的 Test Case 运行结果报告
- O  [0 m6 e4 \5 R " s: @! E) m: r& q


* G3 w* Y! n. q. V8 V: {. T/ A3 j
六、总结
本文通过向读者介绍 JUnit Selenium Adaptor 自动化适配器和 RQM 服务器的连接配置。以及用具体的步骤来演示在 RQM 上执行 Selenium 测试用例,查看执行结果,如何进行调试等场景。让对 RQM 和 Selenium 集成应用有兴趣的读者可以快速入门,并更好的体验这两者集成之后所带来的强大功能。+ M2 G) L% \, v* e

* g; d4 }2 k0 m

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
 楼主| 发表于 2012-12-2 14:46:48 | 显示全部楼层
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

SCMLife推荐上一条 /4 下一条

QQ|小黑屋|手机版|无图版|SCMLife.com ( 京ICP备06056490号-1 )

GMT+8, 2019-7-24 07:14 , Processed in 0.067608 second(s), 8 queries , Gzip On, MemCache On.

Powered by SCMLife X3.4 Licensed

© 2001-2017 JoyShare.

快速回复 返回顶部 返回列表