All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sitoolkit.tester.TestScriptCatalog Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2013 Monocrea Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.sitoolkit.tester;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.sitoolkit.core.infra.repository.DocumentMapper;
import org.sitoolkit.core.infra.repository.DocumentRepository;
import org.sitoolkit.core.infra.repository.RowData;
import org.sitoolkit.core.infra.repository.TableData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;

/**
 *
 * @author yuichi.kuwahara
 */
@Component
@Scope("prototype")
public class TestScriptCatalog {

    protected final Logger log = LoggerFactory.getLogger(getClass());
    @Autowired
    ApplicationContext appCtx;
    @Autowired
    OperationConverter operationConverter;
    /**
     * テストスクリプトの中から
     * ケース番号のカラムを識別するためのプレフィックス
     */
    private String caseNoPrefix = "ケース_";
    /**
     * テストスクリプト内で
     * ケースのテストデータが記載された列番号
     */
    private int caseNoColIndex;
    /**
     * テストスクリプト
     */
    private List testScriptList = new ArrayList();
	/**
	 * キー:スクリプトNo、値:スクリプトNoを持つTestScriptのtestScriptList内のインデックス
	 */
	private Map testScriptNoMap  = new HashMap();
    /**
     * ケース番号マップ
     * キー:ケース番号、値:テストデータ配列のインデックス
     */
    private Map caseNoMap = new HashMap();

    /**
     * テストスクリプトの名前
     */
    private String name;

	/**
	 * 読み込みをケース番号のみに制限する場合にtrue
	 */
	private boolean loadCaseOnly;

	/**
	 * カタログが最後に更新された日時
	 */
	private long lastModified;

	/**
	 * テストスクリプトのファイル
	 */
	private File scriptFile;

	private String sheetName;

    public String getCaseNoPrefix() {
        return caseNoPrefix;
    }

    public void setCaseNoPrefix(String caseNoPrefix) {
        this.caseNoPrefix = caseNoPrefix;
    }

    public List getTestScriptList() {
        return Collections.unmodifiableList(testScriptList);
    }

    public void addTestScript(TestScript testScript) {
        if (testScript != null && testScript.getOperation() != null) {
            testScriptList.add(testScript);
			testScriptNoMap.put(testScript.getNo(), testScriptList.size() - 1);
        }
    }

	public TestScript getTestScript(int index) {
		return testScriptList.get(index);
	}

	public int getTestScriptCount() {
		return testScriptList.size();
	}

	public Integer getScriptIndex(String scriptNo) {
		return testScriptNoMap.get(scriptNo);
	}

    public void setTestScriptList(List testScriptList) {
        this.testScriptList = testScriptList;
    }

    public Map getCaseNoMap() {
        return caseNoMap;
    }

    public void setCaseNoMap(Map caseNoMap) {
        this.caseNoMap = caseNoMap;
    }

    public boolean containsCaseNo(String caseNo) {
        return caseNoMap.containsKey(caseNo);
    }

	public void reload() {
		testScriptList.clear();
		load(scriptFile.getAbsolutePath(), sheetName);
	}

    public void load(String testScriptPath, String sheetName) {
		this.sheetName = sheetName;
        if (testScriptPath.endsWith(".xlsx") || testScriptPath.endsWith("xls")) {
            loadScriptFromExcel(testScriptPath, sheetName);
        } else if (testScriptPath.endsWith(".csv")) {
            loadScriptFromCsv(testScriptPath);
        }
    }

    public void loadScriptFromExcel(String testScriptPath, String sheetName) {
        RowData lastRow = null;
        DocumentRepository repo = appCtx.getBean(DocumentRepository.class);
		TableData table = repo.read(testScriptPath, sheetName);
        DocumentMapper dm = appCtx.getBean(DocumentMapper.class);

		RowData firstRow = table.getRows().iterator().next();
        int testDataIndex = 0;
        for (Map.Entry entry : firstRow.getData().entrySet()) {
            if (entry.getKey().startsWith(getCaseNoPrefix())) {
                String caseNo = StringUtils.substringAfter(entry.getKey(), getCaseNoPrefix());
                caseNoMap.put(caseNo, testDataIndex++);
            }
        }

		if (isLoadCaseOnly()) {
			return;
		}

        for (RowData row : repo.read(testScriptPath, sheetName).getRows()) {
            TestScript testScript = dm.map("testScript", row, TestScript.class);
            addTestScript(testScript);
        }
		try {
			scriptFile = ResourceUtils.getFile(testScriptPath);
			lastModified = scriptFile.lastModified();
			setName(scriptFile.getName());
		} catch (FileNotFoundException e) {
			throw new TestException(e);
		}
    }

    public void loadScriptFromCsv(String testScriptPath) {
        List lineList = null;
        try {
            scriptFile = ResourceUtils.getFile(testScriptPath);
			lastModified = scriptFile.lastModified();
			setName(scriptFile.getName());
            lineList = FileUtils.readLines(scriptFile, "UTF-8");
        } catch (IOException e) {
            throw new TestException(e);
        }
        loadHeader(lineList.get(0));

		if (isLoadCaseOnly()) {
			return;
		}

        for (String line : lineList.subList(1, lineList.size())) {
            if (line.startsWith("#")) {
                log.info("テストスクリプトを除外します。{}", line);
                continue;
            }
            String[] values = splitLine(line);

            log.info("テストスクリプトを追加します。{}", Arrays.toString(values));

            TestScript testScript = appCtx.getBean(TestScript.class);
            testScript.setNo(CsvColumn.no.get(values));
            testScript.setItemName(CsvColumn.itemName.get(values));
            testScript.setOperation(
                (Operation) operationConverter.convert(null, CsvColumn.operation.get(values)));
            testScript.getLocator().setType(CsvColumn.locatorType.get(values));
            testScript.getLocator().setValue(CsvColumn.locator.get(values));
            testScript.setDataType(CsvColumn.dataType.get(values));
            testScript.setScreenshotTiming(CsvColumn.screenshotTiming.get(values));

            Map testDataMap = new HashMap();
            String[] testData = ArrayUtils.subarray(values, caseNoColIndex, values.length);
            for (Map.Entry entry : caseNoMap.entrySet()) {
                String value = entry.getValue() < testData.length
                        ? testData[entry.getValue()]
                        : StringUtils.EMPTY;
                testDataMap.put(entry.getKey(), value);
            }
            log.debug("テストデータを追加します。{}", testDataMap);
            testScript.setTestData(testDataMap);

            addTestScript(testScript);
        }
    }

	public boolean isLoadCaseOnly() {
		return loadCaseOnly;
	}

	public void setLoadCaseOnly(boolean loadCaseOnly) {
		this.loadCaseOnly = loadCaseOnly;
	}

	public boolean isScriptFileChanged() {
		return lastModified != scriptFile.lastModified();
	}

    enum CsvColumn {
        no(0),
        itemName(1),
        operation(2),
        locatorType(3),
        locator(4),
        dataType(5),
        screenshotTiming(6)
        ;
        private int idx;

        private CsvColumn(int idx) {
            this.idx = idx;
        }

        public int getIdx() {
            return idx;
        }

        public String get(String[] values) {
            return values.length <= getIdx()
                    ? StringUtils.EMPTY
                    : values[getIdx()];
        }
    }
    /**
     * テストスクリプトのヘッダー行から
     * ケース番号とテストデータインデックスの対応を読み込み、 ケース番号マップに格納します。
     *
     * @param header ヘッダー行の文字列
     */
    void loadHeader(String header) {
        String[] cells = splitLine(header);

        for (int i = 0; i < cells.length; i++) {
            if (cells[i].startsWith(getCaseNoPrefix())) {
                caseNoColIndex = i;
                break;
            }
        }

        int testDataIndex = 0;
        for (String cell : ArrayUtils.subarray(cells, caseNoColIndex, cells.length)) {
            String caseNo = StringUtils.substringAfter(cell, getCaseNoPrefix());
            caseNoMap.put(caseNo, testDataIndex++);
        }
        log.info("{}件のケースを読み込みます。{}", caseNoMap.size(), caseNoMap.keySet());
    }

    /**
     * 文字列を「,」(半角カンマ)または「\t」(タブ)で分割した文字配列を返します。
     * 分割後の1要素の文字列が「"」(半角ダブルクオーテーション)で開始かつ終了していた場合は、 前後の「"」を除きます。
     *
     * @param line 分割対象の文字列
     * @return 「,」(半角カンマ)または「\t」(タブ)で分割した文字配列
     */
    String[] splitLine(String line) {
        String[] values = line.split(",|\t");
        for (int i = 0; i < values.length; i++) {
            String value = values[i];
            if (value.startsWith("\"") && value.endsWith("\"")) {
                values[i] = value.substring(1, value.length() - 1);
            }
        }
        return values;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

	public int getIndexByScriptNo(String no) {
		return testScriptNoMap.get(no);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy