简体   繁体   English

Jest - 在 describe 块中导入多个测试,重用 beforeEach() 中定义的变量

[英]Jest - import multiple tests in a describe block, reusing variables defined in beforeEach()

I am familiar with RSpec where it is very easy to reuse test cases by writing shared examples我熟悉 RSpec,通过编写共享示例可以很容易地重用测试用例

shared_example_for 'a cute pet' do 
  it 'tests that the pet is a small' { expect(pet.size).to be_lesser_than(10) }
  it 'tests that the pet can smile' { expect(pet.can_smile?).to be }
end

describe 'The Octocat' do
  let(:pet) { Octocat.new }

  it_behaves_like 'a cute pet'
end
...
describe 'The Doge' do 
  let(:pet) { Doge.new }

  it_behaves_like 'a cute pet'
end

Is there an equivalent in Jest ?在 Jest 中有等价物吗? Something that would let me reuse variables set in beforeEach() blocks ?能让我重用在 beforeEach() 块中设置的变量的东西? I am trying to find a way using something like the following :我正在尝试找到一种使用以下内容的方法:

# __tests__/cuteness.js
export const cutenessTests = function() {
  test('it is small', () => {
    expect(petSetInBefore.length).toBeLesserThan(5)
  })
  test('it can smile', () => {
    expect(petSetInBefore.canSmile).toBe(true)
  })
}

# __tests__/famous_animals.test.js
import { cutenessTests } from './cuteness'

describe('Famous animals', () => {
  let petSetInBefore;

  describe('Octocat', () => {
    beforeEach(() => {
      petSetInBefore = new Octocat();
    })

    cutenessTests.bind(this)()
  })
})

The important here is that I am trying to share multiple test definitions and not just one, otherwise I could have passed the petSetInBefore to the shared function.这里重要的是我试图共享多个test定义而不仅仅是一个,否则我可以将 petSetInBefore 传递给共享函数。

EDIT : each of my tests and nested describe are likely to alter my test environment and objects, so the beforeEach is used to restore a proper test environment.编辑:我的每个测试和嵌套描述都可能改变我的测试环境和对象,因此 beforeEach 用于恢复正确的测试环境。 Here is a better example这是一个更好的例子

class Octocat {
  get strokeFor(time) {
    this.strokeTime = this.strokeTime + time
    if (this.strokeTime <= 10) {
      this.mood = 'happy'
    } else {
      this.mood = 'bored'
    }
  }
}

class Doge {
  get strokeFor(time) {
    this.strokeTime = this.strokeTime + time
    if (this.strokeTime <= 5) {
      this.mood = 'happy'
    } else {
      this.mood = 'bored'
    }
  }
}

const cutenessTests = function() {
  describe('when stroked for a short while', () => {
    beforeEach(() => {
      petSetInBefore.strokeFor(1);
    })

    test('it is happy', () => { expect(petSetInBefore.mood).to(eq('happy')) }

    describe('when stroked too much', () => {
      beforeEach(() => {
        petSetInBefore.stroke(1000);
      })

      test('it gets bored', () => { expect(petSetInBefore.mood).to(eq('bored')) }
    })

    describe('when stroked a little longer', () => {
      beforeEach(() => {
        petSetInBefore.strokeFor(4);
      })

      test('it is still happy', () => { expect(petSetInBefore.mood).to(eq('happy')) }
    })
  })
}

EDIT2: Here is a repl.it based on Gui3's answer EDIT2:这里是一个repl.it基于鬲的答案

EDIT3 : the object can be altered before or during the reusable tests EDIT3:在可重用测试之前或期间可以更改对象

describe('Famous animals', () => {
  let petSetInBefore;

  describe('Octocat', () => {
    beforeEach(() => {
      petSetInBefore = new Octocat();
    })

    describe('when it is not well rested', () => { 
      beforeEach(() => { petSetInBefore.wellRested() } // Extra object preparation / context before calling reusable examples
      cutenessTests()
    }),
    describe('when it is not well rested', () => { 
      // Calling reusable examples without extra context
      cutenessTests()
    })
  })
})

You can simply move the shared tests into a function that does the it() calls.您可以简单地将共享测试移动到执行it()调用的函数中。

class Octocat {
  get length() {
    return 3;
  }

  get canSmile() {
    return true;
  }
}

class GrumpyCat {
  get length() {
    return 1;
  }

  get canSmile() {
    return false;
  }
}

const behavesLikeAPet = (pet) => {
  it('is small', () => expect(pet.length).toBeLessThan(5));
  it('can smile', () => expect(pet.canSmile).toEqual(true));
};

describe('Famous animals', () => {
  describe('Octocat', () => {
    behavesLikeAPet(new Octocat());
  });

  describe('GrumpyCat', () => {
    behavesLikeAPet(new GrumpyCat());
  });
});

You will get detailed output for every it test:您将获得每个 it 测试的详细输出:

Famous animals
  Octocat
    ✓ is small (2ms)
    ✓ can smile (1ms)
  GrumpyCat
    ✓ is small
    ✕ can smile (2ms)

If you still want beforeEach ,如果你还想要beforeEach

for reasons ... it works if you declare your variable in the global scope出于某些原因......如果您在全局范围内声明变量,它会起作用

let petSetInBefore; // here it works
describe('Famous animals', () => {
  //let petSetInBefore; // here it's undefined

  describe('Octocat', ()  => {
    //let petSetInBefore; // undefined too

    beforeAll(() => {
      petSetInBefore = new Octocat();
    })

    cutenessTests() // .bind(this) results the same
  });

  describe('Doge', () => {
    beforeEach(() => {
      petSetInBefore = new Doge();
    })

    cutenessTests.bind(this)()
  });
})

https://repl.it/@gui3/jestSharedTests https://repl.it/@gui3/jestSharedTests

seems like the tests inside the shared function cannot share variables from beforeEach otherwise ...似乎共享函数中的测试不能共享beforeEach 中的变量,否则......

Jest has describe.each(table) which I haven't seen being used a lot, but it's really helpful for reusing tests which have common/same results. Jest 有describe.each(table) ,我没有看到它被大量使用,但它对于重用具有共同/相同结果的测试非常有帮助。

In case for identical expectations for both of the test subjects you can do it like this:如果对两个测试对象的期望相同,您可以这样做:

const aCutePet = pet => {
  it("should be small", () => {
    expect(pet.size).toBeLessThan(10);
  });

  it(`should be able to smile`, () => {
    expect(pet).toHaveProperty('can_smile', true)
  });
}

describe.each([
  [new Doge],
  [new Octocat]
])("The %O", aCutePet);

The output:输出:

  The Doge { size: 3, can_smile: true }
    ✓ should be small (1ms)
    ✓ should be able to smile (1ms)
  The Octocat { size: 5, can_smile: true }
    ✓ should be small
    ✓ should be able to smile (1ms)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 运行jasmine测试时,我怎么知道我是否在一个描述块中,在每个块之前还是阻塞? - When running jasmine tests, how can I know if I am in a describe block, beforeEach block or it block? 重用Jest单元测试 - Reusing Jest unit tests 描述块内的 jest.setTimeOut() 是否仅将超时应用于描述块内的测试 - Does jest.setTimeOut() inside a describe block apply the timeout only to tests inside the describe block 笑话:ReferenceError:描述未定义 - Jest : ReferenceError: describe is not defined Jest - 如何让 describe 块访问 beforeAll 中分配的变量? - Jest - How to give describe block access to variables assigned in beforeAll? 开玩笑-describe块的顺序执行 - Jest - Sequential Execution of a describe block 使用不同的beforeEach多次运行测试 - Run tests multiple times with different beforeEach Jest/Express:仅当有多个描述块时,测试才会失败并出现异步错误 - Jest/Express: Tests fail with Async error only when there are multiple describe blocks 在描述内部的beforeEach的开始之前,描述外部的beforeEach会始终完成吗? - Will a beforeEach that is outside a describe always complete before the start of a beforeEach that is inside a describe? 如何在 Jest 中为描述创建一个抽象函数,其中包括几个测试 - How to make an abstract function for describe in Jest, that includes several tests
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM