在做公司 app 自动化测试,在做到 testNG 套件测试的时候,就会报错,详情是:
java.lang.AssertionError: expected object to not be null
at org.testng.Assert.fail(Assert.java:94)
at org.testng.Assert.assertNotNull(Assert.java:404)
at org.testng.Assert.assertNotNull(Assert.java:389)
at com.yiibai.primera.testng.cases.HomeTest.initDriver(HomeTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:138)
at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:175)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:107)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:230)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:76)
部分代码截图:(初始化 dirver 类)
package com.yiibai.primera.testng.base;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.http.util.TextUtils;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Listeners;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import io.appium.java_client.remote.AndroidMobileCapabilityType;
import io.appium.java_client.remote.MobileCapabilityType;
/**
* 测试用例的父类
*/
public class InitAppium {
/*公共参数区*/
public static String device = "Android";
// 调试设备名字
public static String deviceName = "fd47af2d7d42";
public static String udid = deviceName;
// public static String deviceName = "X8QDU14A18000077";
// 调试设备系统版本
public static String platformVersion = "4.1";
//dirver的session的超时时间,默认是60秒
public static String commandTimeout = "6000";
//automationName表示appium使用的测试引擎,默认是appium,也可以是uiautomator
public static String automationName = "appium";
// 不重置应用数据,如重新启动登录过的App时,仍然是登录状态,不需要重新登录
public static String noReset = "True";
/*android特有的配置*/
// 是否不重新签名
public static String noSign = "True";
// unicodeKeyboard设置为true表示我们要使用appium自带的输入法,用来支持中文和隐藏键盘,并且将其设置为默认输入法
public static String unicodeKeyboard = "True";
// 在执行完测试之后,将手机的输入法从appium输入法还原成手机默认输入法
public static String resetKeyboard = "True";
//_当你的其实activity和真正启动后的activity不一致的时候,请把启动的activity放在这里
public static String waitActivity = "";
// app路径
public static String appPath = System.getProperty("user.dir")
+ "/src/main/java/apps/PN_ADS.apk";
// 包名
public static String appPackage = "com.turbo.turbo.mexico";
// 要启动的Activity
// public static String appActivity =".baiyi.jj.app.activity.LogoActivity";
public static String appActivity = "";
public AndroidDriver<AndroidElement> driver;
// 构造方法
public InitAppium() {
this(new Builder());
}
public InitAppium(Builder builder) {
device = builder.device;
deviceName = builder.deviceName;
udid = builder.udid;
commandTimeout = builder.commandTimeout;
automationName = builder.automationName;
platformVersion = builder.platformVersion;
noReset = builder.noReset;
noSign = builder.noSign;
unicodeKeyboard = builder.unicodeKeyboard;
resetKeyboard = builder.resetKeyboard;
appActivity = builder.appActivity;
appPackage = builder.appPackage;
appPath = builder.appPath;
}
/**
* appium启动参数
*
* @throws MalformedURLException
* @throws InterruptedException
*/
@BeforeSuite
public void beforeSuite() throws MalformedURLException, InterruptedException {
System.out.println("beforeSuite begin---");
//启动appium服务
// AppiumDriverLocalService service = AppiumDriverLocalService.buildDefaultService();
// service.start();
DesiredCapabilities capabilities = new DesiredCapabilities();
//共用参数区
capabilities.setCapability("device", device);
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, deviceName);
capabilities.setCapability(MobileCapabilityType.UDID, udid);
capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, platformVersion);
capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, commandTimeout);
capabilities.setCapability(MobileCapabilityType.NO_RESET, noReset);
capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, automationName);
// 支持中文
capabilities.setCapability(AndroidMobileCapabilityType.UNICODE_KEYBOARD, unicodeKeyboard);
capabilities.setCapability(AndroidMobileCapabilityType.RESET_KEYBOARD,resetKeyboard);
capabilities.setCapability(AndroidMobileCapabilityType.NO_SIGN, noSign);
// capabilities.setCapability(AndroidMobileCapabilityType.APP_WAIT_ACTIVITY, waitActivity);
capabilities.setCapability("app", new File(appPath).getAbsolutePath());
capabilities.setCapability("appPackage", appPackage);
// 打开的activity
if (!TextUtils.isEmpty(appActivity)) {
capabilities.setCapability("appActivity", appActivity);
}
// System.out.println("appActivity is: " +
// capabilities.getCapability(appActivity));
// 启动Driver
driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"),
capabilities);
System.out.println("driver is:" + driver);
System.out.println("beforeSuite over----");
}
@AfterSuite
public void afterTest() {
driver.quit();
}
// @AfterClass
// public void afterClass() {
// // 每一个用例完毕结束这次测试
// driver.quit();
// }
/**
* 打印字符 未引用
*
* @param str
* 要打印的字符
*/
public <T> void print(T str) {
if (!TextUtils.isEmpty(String.valueOf(str))) {
System.out.println(str);
} else {
System.out.println("输出了空字符");
}
}
}
测试类:
public class HomeTest extends InitAppium {
private HomeOperate homeOperate;
@BeforeClass
public void initDriver() throws MalformedURLException{
System.out.println("@beforeClass driver is:");
System.out.println(driver);
Assert.assertNotNull(driver); (此处报错,driver为空)
homeOperate = new HomeOperate(driver);
}
/**
* 首页刷新验证
*/
@Test(enabled = false)
public void refresh(){
boolean flag = homeOperate.refresh();
Assertion.verifyEquals(flag,false,"首页刷新验证");
print("首页刷新验证:"+ flag);
}
testNG.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Suite"> <!--parallel="true" 并行 -->
<test name="testAll">
<classes>
<class name="com.yiibai.primera.testng.cases.HomeTest" />
<!-- <class name="com.yiibai.primera.testng.cases.RegisterTest" />
<class name="com.yiibai.primera.testng.cases.LoginTest" />
<class name="com.yiibai.primera.testng.cases.PersonalCenterTest" />
<class name="com.yiibai.primera.testng.cases.NewsDetailsTest" /> -->
</classes>
<listeners>
<listener class-name="org.uncommons.reportng.HTMLReporter" />
<listener class-name="org.uncommons.reportng.JUnitXMLReporter" />
</listeners>
</test><!--Test -->
</suite><!--Suite -->
说明 testNG.xml classes 节点里面,如果只保留一条 class 时是通过的 但是有过多余一条就会报错,初始化 driver 的过程都正常,也初始化成功的,就是在断言 driver 是否为空时报错,driver 为空,求懂的大神帮助下