Java 创建可配置的从属资源 描述
目前,我正在为一项服务创建一些Cumber特性。假设我有一个用于配置特斯拉汽车的服务:Java 创建可配置的从属资源 描述,java,cucumber,cucumber-jvm,Java,Cucumber,Cucumber Jvm,目前,我正在为一项服务创建一些Cumber特性。假设我有一个用于配置特斯拉汽车的服务: public class TeslaCar { Engine engine; Color color; // other things here... } 在哪里 简单的create调用很容易实现,我只是使用Given和Add组合来配置资源,然后调用create 因此,对于CreateEngine,我会: Feature: CreateEngine Scenario Outl
public class TeslaCar {
Engine engine;
Color color;
// other things here...
}
在哪里
简单的create调用很容易实现,我只是使用Given
和Add
组合来配置资源,然后调用create
因此,对于CreateEngine
,我会:
Feature: CreateEngine
Scenario Outline: Create Engine
Given an engine was initialized
And engine has <all_wheel>
And kwh is <kwh>
When engine is created
Then engine creation succeeds
Examples:
| kwh | all_wheel |
| 60 | false |
| 60 | true |
| 70 | false |
问题
一开始这似乎很合理,但有更好的方法吗?如果需要为驱动车配置更多的东西,那么它很快就会变得非常笨拙
问题
@tags
。这会让我说,‘每当我使用@60kWh
,我都需要一台60kWh发动机’。但这并没有得到很好的推广
可能的解决方案2?
不要配置汽车,而是使用默认的。我将压缩向汽车添加发动机等部件的步骤。使用
DataTable
添加引擎的所有属性。从这个新的步骤定义中,您可以调用发动机设置的现有代码,该定义只将DataTable
作为参数。这样,您就不需要每次添加新属性时都添加新的步骤定义。只需附加到DataTable的末尾
如果你有一个新的汽车零部件,你只需要在你的特征文件中添加3行,再加上一个步骤定义。例如,我在功能中添加了一个齿轮箱
如果在功能文件DataTable中,将表头命名为与实例变量相同的名称,则Cucumber将自动将值放入类中,如果您将参数(如List engine
)而不是DataTable
)
我看到的问题是,如果您有一个具有多个设置的属性。例如,发动机模式可以是城市模式、巡航模式和运动模式。也许您可以使用逗号分隔的字符串,然后将其拆分
Feature: Drive Car
Scenario: Test drive Tesla
Given A car with following components
And Add engine with specifications
| kwh | allwheel |
| P90D | true |
And Add gearbox with specifications
| noofgears | auto |
| 4 | true |
And assemble car
When car is driven
Then max speed is 120mph
如果你想要更多的乐趣,考虑一下它是一个场景大纲,测试一个特征中的多个组合。但接下来您将有一个大的示例表,其中包含一行数据。实际上,我会使用这个路由,因为我会从一个场景中获得更多,它会将数据从步骤中推送到示例表中
功能文件中的步骤似乎是对代码的总结,而不是像初始化引擎这样的步骤。但是,如果每个人都理解它并为您的目的服务,为什么要更改它呢。Cucumber是为验收测试而设计的,这些测试按照用户的意愿执行整个系统(因此它们也是集成测试),并且可以被涉众和开发人员理解 您的
CreateEngine
场景并不是针对整个系统,而是针对只对开发人员有意义的软件组件,因此我不会使用Cucumber,而是使用单元测试框架来测试它
另一方面,您的“驾驶汽车”场景是一个合适的验收测试。不过,它有很多软件细节。我会这样写:
Feature: Drive Car
Scenario: Test drive Tesla
Given there is a car with an all-wheel-drive engine and P90D engine kwh
When the car is driven
Then the max speed is 120 mph
(我不确定“P90D engine kwh”的语法是否正确,因此请根据需要更正。)
要点:
- 没有提及软件细节
- 没有提及对结果不重要的价值观;它们只是默认值。请注意,如果存在对结果重要的任何其他值,也应提及这些值,以便读者能够获得验证结果正确性所需的所有信息,而无需阅读步骤定义。例如,如果特斯拉也有尾翼,且尾翼尺寸影响最大速度,则定义汽车的步骤也应提及“大尾翼”或其他内容
另外,不要急于为所有数据组合编写场景(或场景大纲)。验收测试很慢,而且需要维护,所以您希望在向涉众公开所有重要需求的同时,尽可能少地进行验收测试。当你开始编写组合Cucumber场景时,想想你是否可以改为编写一个Cucumber场景作为示例,并在单元测试中测试所有的组合。这是一个非常好的问题,Dave Schweisguth给出了一个很好的答案,我也会补充 当你有一个像你的汽车一样的结构和所有的配置选项,并且你想编写集成测试来处理不同种类的汽车时,你可以通过命名汽车来消除在你的功能中指定每一个保养细节的需要。例如,我可能有:
- 拉力赛车:4轮驱动,6档,超轻底盘, 滚动条
- 出租车:2轮驱动,4档,内部防污
- 中年危机车:四轮驱动,双门轿车,敞篷车,真皮内饰
Given I have a rally car
...
Given I have a taxi
等等等等
现在重要的是,在你身上,无论何时何地,你都不要回到细节
Given I have a taxi
Then I should have 2 wheel drive
And I should have 4 gears
这是不好的,因为您混合了两个抽象级别,详细级别和更高级别。相反,你应该为出租车司机编写出租车场景
e、 g
这意味着你的名字需要对你的利益相关者很重要
这种方法的一个好处是,当您更改规范时,可以降低更改成本。例如,如果我们决定出租车应该是四轮驱动的,我们不必改变每一个场景,我们只需改变步骤def‘给定我有一辆出租车’
我将按如下方式实施步骤defs
Given 'I have a taxi' do
create_taxi
end
module TaxiStepHelper
def create_taxi
create_car(
engine:
drive:
...
)
end
我认为这种方法是“使用更高层次的抽象
Given I have a taxi
Then I should have 2 wheel drive
And I should have 4 gears
Given I have a taxi
When my passengers puke over my interior
Then it should be easy to clean
Given 'I have a taxi' do
create_taxi
end
module TaxiStepHelper
def create_taxi
create_car(
engine:
drive:
...
)
end