Nano Hash - криптовалюты, майнинг, программирование

Jest - импортировать несколько тестов в блок описания, повторно используя переменные, определенные в beforeEach ()

Я знаком с 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

Есть ли в Jest аналог? Что-то, что позволило бы мне повторно использовать переменные, заданные в блоках beforeEach ()? Я пытаюсь найти способ, используя что-то вроде следующего:

# __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)()
  })
})

Здесь важно то, что я пытаюсь поделиться несколькими test определениями, а не одним, иначе я мог бы передать petSetInBefore общей функции.

РЕДАКТИРОВАТЬ: каждый из моих тестов и вложенных описаний, вероятно, изменит мою тестовую среду и объекты, поэтому beforeEach используется для восстановления надлежащей тестовой среды. Вот лучший пример

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: вот repl.it на основе Ответ Gui3

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()
    })
  })
})

  • Примечание: хотя это может быть полезно при массовом повторном использовании тестов, на самом деле мы предпочитаем до некоторой степени дублировать тестовый код, чтобы облегчить статический анализ и воспользоваться возможностями IDE. Например, Visual Studio Code может автоматически запускать ваши тесты, пока вы их пишете, и указывать красными / зелеными кружками, какие тесты прошли в фоновом режиме: он не будет работать в таких ситуациях. Но если вам нужно повторно использовать серию тестов для большого количества файлов (страница требует аутентификации, запретить доступ заблокированным пользователям и т. Д.), Это все равно может быть полезно. 30.11.2019

Ответы:


1

Если вы по-прежнему хотите beforeEach,

по причинам ... он работает, если вы объявляете свою переменную в глобальной области

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

похоже, что тесты внутри общей функции не могут использовать переменные из beforeEach, иначе ...

24.11.2019
  • Спасибо, я расширил ваши тесты, чтобы учесть мое РЕДАКТИРОВАНИЕ, оказалось, что мне нужно beforeEach, чтобы убедиться, что тестовые объекты чистые repl.it/repls/LawfulDelightfulAbility 30.11.2019
  • Я не полностью удовлетворен решением, поскольку оно включает глобальные переменные, которые не имеют области видимости, но я думаю, что это останется принятым ответом до тех пор, пока не появится что-то новое, что можно было бы привязать к блоку описания. И, вероятно, наличие глобальных переменных в тестах не такая уж большая проблема, поскольку я думаю, шутка уберет их при выполнении разных тестов? 30.11.2019

  • 2

    Вы можете просто переместить общие тесты в функцию, которая выполняет 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());
      });
    });
    

    Вы получите подробный вывод по каждому тесту:

    Famous animals
      Octocat
        ✓ is small (2ms)
        ✓ can smile (1ms)
      GrumpyCat
        ✓ is small
        ✕ can smile (2ms)
    
    24.11.2019
  • Спасибо. Я отредактировал свой вопрос: уловка в том, что мой объект может измениться при выполнении тестов, и важно, чтобы перед каждым тестом я правильно восстанавливал тестовую среду. Поэтому использование одного new Octocat() невозможно, и он должен быть новым объектом в каждом тесте. 30.11.2019
  • @ CyrilDuchon-Doris Значит, вам нужен совершенно новый экземпляр питомца для каждого it() вызова? Вы можете просто передать имя класса behavesLikeAPet и позволить каждому it() создать новый экземпляр: it('is small', () => expect((new Pet()).length).toBeLessThan(5)); 30.11.2019

  • 3

    У Jest есть describe.each(table), который я не видел часто, но это действительно полезно для повторного использования тестов, которые дают общие / одинаковые результаты.

    В случае одинаковых ожиданий от обоих испытуемых, вы можете сделать это следующим образом:

    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 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)
    
    24.11.2019
  • Вышеупомянутые решения не помогли мне при интеграции с Playwright и работе с входом в систему и навигацией. Тесты зависали и терпели неудачу. Я предпочитаю этот ответ, потому что он легко доступен через шутку и хорошо работает. 07.05.2020
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..