package org.test4j.spec.scenario;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.test4j.spec.inner.IScenario;
import org.test4j.spec.inner.IScenarioStep;
import org.test4j.spec.reader.LinesReader;
import org.test4j.spec.reader.StreamLinesReader;
import org.test4j.spec.reader.StringLinesReader;
import org.test4j.spec.scenario.step.JSpecStep;
import org.test4j.spec.scenario.step.TxtJSpecStep;
import org.test4j.spec.scenario.step.TxtJSpecStep.TxtJSpecStepTemplate;
import org.test4j.spec.scenario.step.txt.LineType;
/**
* 文本文件描述的故事场景解析器
*
* @author darui.wudr 2012-6-28 下午3:26:22
*/
public class TxtJSpecScenario extends JSpecScenario {
public TxtJSpecScenario(List<String> lines, List<IScenarioStep> templates) {
this.parse(lines, templates);
}
private void parse(List<String> lines, List<IScenarioStep> templates) {
StringBuilder buff = new StringBuilder();
JSpecStep step = null;
IScenarioStep template = null;
for (String line : lines) {
LineType type = LineType.getLineType(line);
switch (type) {
case Scenario:
this.scenario = line.substring(8).trim();
this.isSkip = false;
break;
case SkipScenario:
this.scenario = line.substring(12).trim();
this.isSkip = true;
break;
// all kinds of GWZ line
case Given:
case SkipGiven:
case When:
case SkipWhen:
case Then:
case SkipThen:
addStep(buff, step, template);
step = new TxtJSpecStep(this.scenario, line, type);
template = JSpecStep.findTemplate(templates, step.getMethod(), step.getType());
buff = new StringBuilder();
break;
case TextLine:
default:
if (buff.length() != 0) {
buff.append("\n");
}
buff.append(line);
break;
}
}
this.addStep(buff, step, template);
}
/**
* 往列表中增加步骤
*
* @param buff
* @param step
*/
private void addStep(StringBuilder buff, JSpecStep step, IScenarioStep template) {
if (step == null) {
this.description = buff.toString();
} else {
step.parseStep(buff.toString(), template);
this.steps.add(step);
}
}
static Story parseJSpecScenarioFrom(LinesReader reader) {
Story story = parseTxtStoryFeatureFrom(reader);
return story;
}
public static Story parseTxtStoryFeatureFrom(LinesReader reader) {
Story storyFeature = new Story();
try {
String line = parseStepTemplates(reader, storyFeature);
// 如果已经读完文本,直接返回
if (line == null) {
return storyFeature;
}
// 依次读取每个场景的文本描述
List<String> lines = new ArrayList<String>();
lines.add(line);
//当前场景类型
LineType currScenarioType = LineType.scenarioType(line);
do {
line = reader.readLine();
if (line == null || LineType.isScenarioLine(line)) {
IScenario scenario = new TxtJSpecScenario(lines, storyFeature.getTemplates());
if (currScenarioType == LineType.BeforeScenario) {
storyFeature.setBeforeScenario(scenario);
} else if (currScenarioType == LineType.AfterScenario) {
storyFeature.setAfterScenario(scenario);
} else {
scenario.setIndex(storyFeature.getScenarios().size() + 1);
storyFeature.getScenarios().add(scenario);
}
if (line != null) {
lines = new ArrayList<String>();
lines.add(line);
currScenarioType = LineType.scenarioType(line);
}
} else {
lines.add(line);
}
} while (line != null);
return storyFeature;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
reader.close();
}
}
/**
* 解析模板方法列表
*
* @param reader
* @param templates
* @return
* @throws IOException
*/
static String parseStepTemplates(LinesReader reader, Story storyFeature) throws IOException {
String line = reader.readLine();
// 跳过第一个场景或模板之前的描述文字
StringBuffer description = new StringBuffer();
while (line != null && !LineType.isScenarioLine(line) && !LineType.isTemplateLine(line)) {
description.append(line);
line = reader.readLine();
continue;
}
storyFeature.setDescription(description.toString());
List<String> lines = null;
while (line != null && !LineType.isScenarioLine(line)) {
if (LineType.isTemplateLine(line) || lines == null) {
addTemplate(storyFeature.getTemplates(), lines);
lines = new ArrayList<String>();
lines.add(line);
} else {
lines.add(line);
}
line = reader.readLine();
}
addTemplate(storyFeature.getTemplates(), lines);
return line;
}
/**
* 增加模板列表
*
* @param templates
* @param lines
*/
private static void addTemplate(List<IScenarioStep> templates, List<String> lines) {
if (lines == null || lines.size() == 0) {
return;
}
String capital = null;
StringBuilder buff = new StringBuilder();
for (String line : lines) {
if (capital == null) {
capital = line;
} else {
buff.append(line);
}
}
JSpecStep template = new TxtJSpecStepTemplate(capital, LineType.getLineType(capital));
template.parseStep(buff.toString(), null);
templates.add(template);
}
public static Story parseJSpecScenarioFrom(String storyContext) {
String lines[] = storyContext.split("\n");
LinesReader reader = new StringLinesReader(lines);
Story story = parseJSpecScenarioFrom(reader);
return story;
}
/***
* 从文本流中解析需要运行的测试场景
*
* @param is
* @param encoding 文本流编码,如果为null,则自动获取,如果自动获取失败,则使用默认编码
* @return
*/
public static Story parseJSpecScenarioFrom(InputStream is, String encoding) {
LinesReader reader = new StreamLinesReader(is, encoding);
Story story = parseJSpecScenarioFrom(reader);
return story;
}
}