Previewer支持自动化测试默认开启

Signed-off-by: wangweiyuan <wangweiyuan2@huawei.com>
This commit is contained in:
wangweiyuan 2024-09-10 21:16:43 +08:00
parent 1f140e42ba
commit 7df3826b5e
11 changed files with 1234 additions and 166 deletions

View File

@ -11,4 +11,4 @@
# See the License for the specific language governing permissions and
# limitations under the License.
enable_component_test = false
enable_component_test = true

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
#include "component_test\test_config.h"
#include "component_test/test_config.h"
#include <functional>
#include <string>

View File

@ -32,7 +32,7 @@ async function getFolders(filePath) {
async function createCsvData(casePath) {
const csvContext = [];
let index = 1;
const projectPath = path.join(casePath, "test", "componenttest", "test_cases", "components");
const projectPath = path.join(casePath, "test", "component_test", "test_cases", "components");
try {
const projectNames = await getFolders(projectPath);

View File

@ -75,11 +75,9 @@ function setFile(flieData) {
fs.writeFile(filePathData, data, (err) => {
if (err) throw err;
console.log('数据已被写入到文件');
});
try {
fs.writeFileSync(filePathData, data);
console.log('数据已被写入到文件');
return filePathData;
} catch (err) {
throw err;

View File

@ -30,142 +30,134 @@ const args = process.argv.slice(2);
const originUrl = args[0];
const testFilePath = args[1];
function parameters(sdkPath, access_token, downloadPath, resultPath, casePath, devEcoPath, concurrentQuantity) {
this.sdkPath = sdkPath;
this.access_token = access_token;
this.downloadPath = downloadPath;
this.resultPath = resultPath;
this.casePath = casePath;
this.devEcoPath = devEcoPath;
this.concurrentQuantity = concurrentQuantity;
function Parameters(sdkPath, access_token, downloadPath, resultPath, casePath, devEcoPath, concurrentQuantity) {
this.sdkPath = sdkPath;
this.access_token = access_token;
this.downloadPath = downloadPath;
this.resultPath = resultPath;
this.casePath = casePath;
this.devEcoPath = devEcoPath;
this.concurrentQuantity = concurrentQuantity;
}
const createQueueWithHvigor = () => {
return async.queue(async (param, callback) => {
await runHvigor(param.sdkPath, param.testFile, param.resultPath, param.casePath, param.ohpmBat, param.nodePath
, param.hvigorPath);
callback();
}, 1);
return async.queue(async (param, callback) => {
await runHvigor(param.sdkPath, param.testFile, param.resultPath, param.casePath, param.ohpmBat, param.nodePath
, param.hvigorPath);
callback();
}, 1);
};
const createQueueWithConcurrency = (concurrencyLimit) => {
return async.queue(async (param, callback) => {
await test(param.sdkPath, param.testFile, param.resultPath, param.casePath, param.ohpmBat, param.nodePath
, param.hvigorPath);
callback();
}, concurrencyLimit);
return async.queue(async (param, callback) => {
await test(param.sdkPath, param.testFile, param.resultPath, param.casePath, param.ohpmBat, param.nodePath
, param.hvigorPath);
callback();
}, concurrencyLimit);
};
function TestParam(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath) {
this.sdkPath = sdkPath;
this.testFile = testFile;
this.resultPath = resultPath;
this.casePath = casePath;
this.ohpmBat = ohpmBat;
this.nodePath = nodePath;
this.hvigorPath = hvigorPath;
this.sdkPath = sdkPath;
this.testFile = testFile;
this.resultPath = resultPath;
this.casePath = casePath;
this.ohpmBat = ohpmBat;
this.nodePath = nodePath;
this.hvigorPath = hvigorPath;
}
async function run(url, htmlName, testFiles, downloadPath, resultFolder, sdkPath, casePath,
concurrentQuantity, datetime, ohpmBat, nodePath, hvigorPath) {
let startTime = new Date().getTime();
await prepareHostEnv(url, downloadPath, sdkPath)
.catch(error => {
throw error;
});
let originPIDs = await getNodePIDs();
let projectName;
const queueHvigor = createQueueWithHvigor();
for (let i = 0; i < testFiles.length; i++) {
const resultPath = path.join(resultFolder, datetime, testFiles[i][0]);
let testFile = testFiles[i];
if (projectName != testFile[0]) {
await queueHvigor.push(new TestParam(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath));
projectName = testFile[0];
concurrentQuantity, datetime, ohpmBat, nodePath, hvigorPath) {
let startTime = new Date().getTime();
let downloadResultPath = path.join(downloadPath, "downloadResult");
await prepareHostEnv(url, downloadResultPath, sdkPath)
.catch(error => {
throw error;
});
let originPIDs = await getNodePIDs();
let projectName = "";
const queueHvigor = createQueueWithHvigor();
for (let i = 0; i < testFiles.length; i++) {
const resultPath = path.join(resultFolder, datetime, testFiles[i][0]);
let testFile = testFiles[i];
if (projectName !== testFile[0]) {
queueHvigor.push(new TestParam(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath));
projectName = testFile[0];
}
}
}
queueHvigor.drain(() => {
console.log('Successfully runHvigor all');
});
const queue = createQueueWithConcurrency(concurrentQuantity);
for (let i = 0; i < testFiles.length; i++) {
const resultPath = path.join(resultFolder, datetime, testFiles[i][0]);
let testFile = testFiles[i];
queue.push(new TestParam(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath), () => {
console.log("complete", i + 1);
queueHvigor.drain(() => {
const queue = createQueueWithConcurrency(concurrentQuantity);
for (let i = 0; i < testFiles.length; i++) {
const resultPath = path.join(resultFolder, datetime, testFiles[i][0]);
let testFile = testFiles[i];
queue.push(new TestParam(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath));
}
queue.drain(async () => {
const htmlPath = path.join(resultFolder, datetime);
readDir(htmlPath)
.then((file, err) => {
if (err) {
console.error(err);
}
if (file.length > 0) {
generateHTML(htmlPath, htmlName, startTime);
} else {
console.error('resultPath directory is empty.');
}
});
getNodePIDs()
.then((pIds, err) => {
if (err) {
console.error(err);
}
let runOverPIDs = [...pIds];
for (let i = 0; i < originPIDs.length; i++) {
for (let j = 0; j < runOverPIDs.length; j++) {
if (originPIDs[i] === runOverPIDs[j]) {
runOverPIDs.splice(j, 1);
}
}
}
deleteNodePIDs(runOverPIDs)
.then((code, err) => {
if (err) {
console.error(err);
}
}).catch((error) => {
console.error(error);
});
});
await deleteDir(sdkPath);
await renameDir(`${sdkPath}-backup`, sdkPath);
})
});
}
queue.drain(() => {
console.log('Successfully processed all items');
const htmlPath = path.join(resultFolder, datetime);
readDir(htmlPath)
.then((file, err) => {
if (err) {
console.error(err);
}
if (file.length > 0) {
generateHTML(htmlPath, htmlName, startTime);
} else {
console.error('resultPath directory is empty.');
}
});
console.log('Started to kill node');
getNodePIDs()
.then((pIds, err) => {
if (err) {
console.error(err);
}
let runOverPIDs = [...pIds];
for (let i = 0; i < originPIDs.length; i++) {
for (let j = 0; j < runOverPIDs.length; j++) {
if (originPIDs[i] === runOverPIDs[j]) {
runOverPIDs.splice(j, 1);
}
}
};
deleteNodePIDs(runOverPIDs)
.then((code, err) => {
if (err) {
console.error(err);
}
console.log(code);
}).catch((error) => {
console.log(error);
});
});
});
}
async function main() {
const testFiles = await parseJson(testFilePath);
const datetime = getDateTime();
let prNumber = originUrl.split("/")[originUrl.split("/").length - 1];
const htmlName = `${datetime}_${prNumber}.html`;
let jsonData = parseJson('param.json');
let param = new parameters(jsonData.sdkPath, jsonData.access_token, jsonData.downloadPath, jsonData.resultPath,
jsonData.casePath, jsonData.devEcoPath, jsonData.concurrentQuantity);
let ohpmBat = `${param.devEcoPath}\\tools\\ohpm\\bin\\ohpm.bat`;
let nodePath = `${param.devEcoPath}\\tools\\node\\node.exe`;
let hvigorPath = `${param.devEcoPath}\\tools\\hvigor\\bin\\hvigorw.js`;
try {
const evolveUrl = originUrl.slice(18);
let requestUrl =
`https://gitee.com/api/v5/repos/${evolveUrl}/comments?access_token=${param.access_token}` +
`&page=1&per_page=50&direction=desc`;
await run(requestUrl, htmlName, testFiles, param.downloadPath, param.resultPath, param.sdkPath,
param.casePath, jsonData.concurrentQuantity, datetime, ohpmBat, nodePath, hvigorPath)
.catch(err => {
const testFiles = await parseJson(testFilePath);
const datetime = getDateTime();
let prNumber = originUrl.split("/")[originUrl.split("/").length - 1];
const htmlName = `${datetime}_${prNumber}.html`;
let jsonData = parseJson('param.json');
let param = new Parameters(jsonData.sdkPath, jsonData.access_token, jsonData.downloadPath, jsonData.resultPath,
jsonData.casePath, jsonData.devEcoPath, jsonData.concurrentQuantity);
let ohpmBat = `${param.devEcoPath}\\tools\\ohpm\\bin\\ohpm.bat`;
let nodePath = `${param.devEcoPath}\\tools\\node\\node.exe`;
let hvigorPath = `${param.devEcoPath}\\tools\\hvigor\\bin\\hvigorw.js`;
try {
const evolveUrl = originUrl.slice(18);
let requestUrl =
`https://gitee.com/api/v5/repos/${evolveUrl}/comments?access_token=${param.access_token}` +
`&page=1&per_page=50&direction=desc`;
await run(requestUrl, htmlName, testFiles, param.downloadPath, param.resultPath, param.sdkPath,
param.casePath, jsonData.concurrentQuantity, datetime, ohpmBat, nodePath, hvigorPath)
.catch(err => {
throw err;
});
} catch (err) {
process.exit(1);
throw err;
});
console.log('测试执行完毕,恢复previewer的sdk');
deleteDir(sdkPath);
console.log(`删除了${sdkPath}`);
renameDir(`${sdkPath}-backup`, sdkPath);
console.log('已恢复至初始状态');
} catch (err) {
process.exit(1);
throw err;
}
}
}
main();

View File

@ -32,7 +32,7 @@ let origin = 40001;
async function test(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath) {
return new Promise(async (resolve, reject) => {
const testCasePath = `${casePath}\\test\\componenttest\\test_cases\\components\\${testFile[0]}`;
const testCasePath = `${casePath}\\test\\component_test\\test_cases\\components\\${testFile[0]}`;
const previewerExePath = `${sdkPath}\\previewer\\common\\bin`;
const jParam = `${testCasePath}\\entry\\.preview\\default\\intermediates\\loader_out\\default\\ets`;
const ljPathParam = `${testCasePath}\\entry\\.preview\\default\\intermediates\\loader\\default\\loader.json`;
@ -70,11 +70,9 @@ const runCommand = (command, args, options) => {
let stdoutData = "";
let stderrData = "";
child.stdout.on('data', data => {
console.log(data.toString());
stdoutData += data.toString();
});
child.stderr.on('data', (data) => {
console.log(data.toString());
stderrData += data.toString();
if (data.toString().includes("ERROR")) {
resolve(false)
@ -91,7 +89,7 @@ const runCommand = (command, args, options) => {
};
async function runHvigor(sdkPath, testFile, resultPath, casePath, ohpmBat, nodePath, hvigorPath) {
const testCasePath = `${casePath}\\test\\componenttest\\test_cases\\components\\${testFile[0]}`;
const testCasePath = `${casePath}\\test\\component_test\\test_cases\\components\\${testFile[0]}`;
const fParam = `${testCasePath}\\.idea\\previewer\\default\\defaultSettingConfig_Default.json`;
const caseResultPath = `${resultPath}\\${testFile[2]}.json`.replaceAll("\\", "\\\\");
runCommand(`"${ohpmBat}"`, [
@ -211,7 +209,6 @@ async function runPreviewer(
'-componentTest', `"${componentTestParam}"`
], { detached: true, cwd: previewerExePath, shell: true });
previewerProcess.on('close', (code) => {
console.log(`Previewer process exited with code ${code}`);
resolve(true);
});
previewerProcess.on('error', (err) => {

View File

@ -311,5 +311,5 @@ async function generateHTML(resultPath, htmlName, startTime) {
</html>
`;
fs.writeFileSync(path.join(resultPath, htmlName), htmlContent);
console.log(`HTML file with stacked bar chart generated: ${htmlName}`);
console.info(`HTML file with stacked bar chart generated: ${htmlName}`);
}

View File

@ -18,7 +18,9 @@ const path = require('path');
const { JSDOM } = require('jsdom');
const os = require('os');
const unzipper = require('unzipper');
const { clearDir, deleteDir, existDir, mkdir, moveDir, readDir, renameDir } = require('../utils/file.js');
const {
clearDir, deleteDir, existDir, mkdir, moveDir, readDir, renameDir, isExistFile, copyFile
} = require('../utils/file.js');
const http = require("http");
module.exports = { prepareHostEnv };
@ -28,7 +30,6 @@ async function getPullsNumberComments(url) {
if (response.ok) {
const data = await response.json();
for (let i = 0; i < data.length; i++) {
const date = new Date(data[i].updated_at);
if (data[i].body.includes("代码门禁通过")) {
const dom = new JSDOM(data[i].body);
const document = dom.window.document;
@ -49,21 +50,30 @@ async function getPullsNumberComments(url) {
}
async function downloadFile(url, destinationPath) {
return new Promise((resolve, reject) => {
return new Promise(async (resolve, reject) => {
const fileStream = fs.createWriteStream(destinationPath);
const request = http.get(url, (response) => {
if (response.statusCode !== 200) {
const request = await http.get(url, (response) => {
if (response.statusCode === 404) {
console.error("当前PR地址已失效请更换可用的PR地址后重试");
reject(false);
} else {
console.log("开始下载");
response.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close();
resolve(true);
});
return;
}
if (response.statusCode !== 200) {
console.error("下载失败");
reject(false);
return;
}
response.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close(() => resolve(true));
});
fileStream.on('error', (error) => {
console.error("下载文件错误", error);
reject(false);
});
});
request.on('error', (error) => {
console.error("请求出错", error);
reject(false);
});
});
@ -89,7 +99,6 @@ async function extractLargeZip(zipFilePath, outputDir) {
throw error;
})
.on('close', () => {
console.log('解压完成');
resolve();
});
});
@ -100,15 +109,12 @@ function judgePlatform() {
}
async function extractZipFile(zipFilePath, outputDirectory) {
console.log('zip 文件路径:', zipFilePath);
console.log('输出目录:', outputDirectory);
try {
await new Promise((resolve, reject) => {
fs.createReadStream(zipFilePath)
.pipe(unzipper.Extract({ path: outputDirectory }))
.on('error', reject)
.on('finish', () => {
console.log('解压完成');
resolve();
});
});
@ -125,52 +131,55 @@ async function downloadSdk(url, downloadPath) {
try {
const pullsNumberCommentsResponse = await getPullsNumberComments(url);
if (pullsNumberCommentsResponse !== null && pullsNumberCommentsResponse.hrefValue !== "") {
const downloadResult = await downloadFile(
pullsNumberCommentsResponse.hrefValue, path.join(downloadPath, "ohos-sdk.zip"));
resolve(downloadResult);
await downloadFile(pullsNumberCommentsResponse.hrefValue,
path.join(downloadPath, "ohos-sdk.zip")).then((res, rej) => {
if (res) {
resolve(true);
} else {
reject(false);
}
})
} else {
console.warn("暂时没有ohos-sdk");
console.error("暂无可用sdk");
reject(false);
}
} catch (error) {
throw error;
console.error("下载过程中发生错误");
reject(false);
}
});
}
async function prepareHostEnv(url, downloadPath, sdkPath) {
try {
let ohosSdkPath;
let etsPath = path.join(sdkPath, "ets\\api");
const existSdk = await existDir(downloadPath);
if (existSdk) {
console.log(`清空${downloadPath}文件夹`);
await clearDir(downloadPath);
} else {
console.log(`创建${downloadPath}文件夹`);
await mkdir(downloadPath);
}
const existSdkPath = await existDir(sdkPath);
const existBackUpSdkPath = await existDir(`${sdkPath}-backup`);
if (existBackUpSdkPath) {
await deleteDir(`${sdkPath}-backup`);
}
if (existSdkPath) {
console.log(`备份${sdkPath}文件夹`);
await renameDir(sdkPath, `${sdkPath}-backup`);
await mkdir(sdkPath);
} else {
console.log(`创建${sdkPath}文件夹`);
await mkdir(sdkPath);
}
const downloadResult = await downloadSdk(url, downloadPath);
console.log("SDK下载成功:", downloadResult);
console.log("解压下载的文件");
await downloadSdk(url, downloadPath);
await extractLargeZip(path.join(downloadPath, "ohos-sdk.zip"), downloadPath);
let ohosSdkPath;
if (judgePlatform) {
ohosSdkPath = path.join(downloadPath, 'ohos-sdk\\windows');
ohosSdkPath = path.join(downloadPath, 'windows');
} else {
ohosSdkPath = path.join(downloadPath, 'ohos-sdk\\linux');
ohosSdkPath = path.join(downloadPath, 'linux');
}
console.log(`当前操作系统是${os.platform()}`);
let zipFiles = await readDir(ohosSdkPath);
for (let i = 0; i < zipFiles.length; i++) {
@ -183,8 +192,25 @@ async function prepareHostEnv(url, downloadPath, sdkPath) {
await moveDir(sdks[i], sdkPath);
}
}
await deleteDir(downloadPath);
let etsFile = path.join(etsPath, "@ohos.arkui.componentTest.d.ts");
if (await isExistFile(etsFile)) {
await copyFile("previewer_host\\resource\\componentTest.ts", etsFile)
}
} catch (error) {
console.log("准备环境过程出错,恢复初始状态");
if (await isExistFile(downloadPath)) {
await clearDir(downloadPath);
}
if (await isExistFile(sdkPath)) {
await deleteDir(sdkPath);
}
if (await isExistFile(`${sdkPath}-backup`)) {
await renameDir(`${sdkPath}-backup`, sdkPath);
}
console.log("环境清理完成");
throw error;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -22,8 +22,10 @@ module.exports = {
readDir,
clearDir,
deleteDir,
delFile,
renameDir,
moveDir,
moveSourceToTarget,
writeJsonFile,
isExistFile,
recursiveCreateFolders,
@ -90,6 +92,14 @@ async function deleteDir(folderPath) {
}
}
async function delFile(filePath) {
try {
await fs.rm(filePath, { recursive: true });
} catch (err) {
if (err.code !== 'ENOENT') throw err;
}
}
async function renameDir(oldName, newName) {
try {
await fs.rename(oldName, newName);

View File

@ -74,7 +74,6 @@ async function deleteNodePIDs(PIDs) {
deleteProcess.stdout.on('data', data => {
stdout += data.toString();
console.log(data.toString());
});
deleteProcess.stderr.on('data', data => {
@ -87,7 +86,6 @@ async function deleteNodePIDs(PIDs) {
console.error(`delete process error exited with code ${code}`);
reject(code);
} else {
console.log(`process exited with code ${code}`);
resolve(code);
}
});