Что такое маги c под блоком «тогда» Спока? - PullRequest
0 голосов
/ 29 января 2020

Я новичок в Groovy / Spock, и мне любопытно понять под прикрытием синтаксиса "then" блока:

def "my specification"() {
    given:
        int a = 1
    when:
        ++a
    then:
        a == 1
        a > 0
        a != 2
}

Как фреймворк оценивает отдельно 3 последние строки этого метода?

Ответы [ 2 ]

1 голос
/ 30 января 2020

В дополнение к сказанному tim_yates и injecteer приведен результат декомпиляции Fernflower (выполненной в IntelliJ IDEA) следующей спецификации:

package de.scrum_master.stackoverflow

import spock.lang.Specification

class DummyTest extends Specification {
  def "my specification"() {
    given:
    int a = 1
    when:
    ++a
    then:
    a == 2
    a > 1
    a != 3
  }
}
package de.scrum_master.stackoverflow;

import groovy.lang.GroovyObject;
import org.codehaus.groovy.runtime.BytecodeInterface8;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
import org.spockframework.runtime.ErrorCollector;
import org.spockframework.runtime.SpockRuntime;
import org.spockframework.runtime.ValueRecorder;
import org.spockframework.runtime.model.BlockKind;
import org.spockframework.runtime.model.BlockMetadata;
import org.spockframework.runtime.model.FeatureMetadata;
import org.spockframework.runtime.model.SpecMetadata;
import spock.lang.Specification;

@SpecMetadata(
  filename = "DummyTest.groovy",
  line = 5
)
public class DummyTest extends Specification implements GroovyObject {
  public DummyTest() {
    CallSite[] var1 = $getCallSiteArray();
    super();
  }

  @FeatureMetadata(
    line = 6,
    name = "my specification",
    ordinal = 0,
    blocks = {@BlockMetadata(
  kind = BlockKind.SETUP,
  texts = {}
), @BlockMetadata(
  kind = BlockKind.WHEN,
  texts = {}
), @BlockMetadata(
  kind = BlockKind.THEN,
  texts = {}
)},
    parameterNames = {}
  )
  public void $spock_feature_0_0() {
    CallSite[] var1 = $getCallSiteArray();
    ErrorCollector $spock_errorCollector = (ErrorCollector)ScriptBytecodeAdapter.castToType(var1[0].callConstructor(ErrorCollector.class, false), ErrorCollector.class);
    ValueRecorder $spock_valueRecorder = (ValueRecorder)ScriptBytecodeAdapter.castToType(var1[1].callConstructor(ValueRecorder.class), ValueRecorder.class);

    Object var10000;
    try {
      int a = 1;
      int a;
      if (BytecodeInterface8.isOrigInt() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()) {
        a = a + 1;
      } else {
        a = DefaultTypeTransformation.intUnbox(var1[2].call(Integer.valueOf(a)));
      }

      try {
        SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), "a == 2", Integer.valueOf(12), Integer.valueOf(5), (Object)null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(2)), ScriptBytecodeAdapter.compareEqual($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(0)), a), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(1)), 2))));
        var10000 = null;
      } catch (Throwable var44) {
        SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, "a == 2", Integer.valueOf(12), Integer.valueOf(5), (Object)null, var44);
        var10000 = null;
      } finally {
        ;
      }

      try {
        SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), "a > 1", Integer.valueOf(13), Integer.valueOf(5), (Object)null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(2)), ScriptBytecodeAdapter.compareGreaterThan($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(0)), a), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(1)), 1))));
        var10000 = null;
      } catch (Throwable var42) {
        SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, "a > 1", Integer.valueOf(13), Integer.valueOf(5), (Object)null, var42);
        var10000 = null;
      } finally {
        ;
      }

      try {
        SpockRuntime.verifyCondition($spock_errorCollector, $spock_valueRecorder.reset(), "a != 3", Integer.valueOf(14), Integer.valueOf(5), (Object)null, $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(2)), ScriptBytecodeAdapter.compareNotEqual($spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(0)), a), $spock_valueRecorder.record($spock_valueRecorder.startRecordingValue(Integer.valueOf(1)), 3))));
        var10000 = null;
      } catch (Throwable var40) {
        SpockRuntime.conditionFailedWithException($spock_errorCollector, $spock_valueRecorder, "a != 3", Integer.valueOf(14), Integer.valueOf(5), (Object)null, var40);
        var10000 = null;
      } finally {
        ;
      }

      var1[3].call(var1[4].call(this.getSpecificationContext()));
    } finally {
      $spock_errorCollector.validateCollectedErrors();
      var10000 = null;
    }

  }
}

Ссылка Тима дает вам дополнительную справочную информацию. Как видите, это больше, чем просто добавление assert, это больше похоже на SpockRuntime.verifyCondition(..), завернутый в try-catch.

0 голосов
/ 29 января 2020

then сама по себе является простой старой меткой Java.

Каждая строка является новым вызовом >> Java ; может быть пропущено.

Каждый вызов находится внутри оператора Groovy assert, который также может быть выполнен вне Spock:

int a = 1
assert a
assert 0 < a
assert !a // here assertion error
...