Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Тестирование на основе сетей Петри

Тестирование на основе сетей Петри

A talk about automated exploratory testing based on Petri net models for HeisenBug Piter 2018 (https://2018.heisenbug-piter.ru/talks/2018/spb/6feubdtqqwqocya2w4cwq2/). The recording of the talk is available on YouTube (https://www.youtube.com/watch?v=TeKHZw61pb8).

D049f551aa71e6326c74002ac8e6788a?s=128

Alex Rodionov

May 17, 2018
Tweet

Transcript

  1. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ

  2. ! Лёша Родионов 2

  3. ! Лёша Родионов 3

  4. ! Лёша Родионов @p0deje 4

  5. ! Лёша Родионов @p0deje 5

  6. ! Лёша Родионов @p0deje 6

  7. ! Лёша Родионов @p0deje 7

  8. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ

  9. ДЛЯ КОГО? 9

  10. ДЛЯ КОГО? 1.Для тех, у кого много тестов и багов.

    10
  11. ДЛЯ КОГО? 1.Для тех, у кого много тестов и багов.

    2.Для тех, кто только планирует автоматизированное тестирование. 11
  12. 1. Недостаточность обычных тестов
 
 


  13. 1. Недостаточность обычных тестов 2. Тестирование на основе моделей
 


  14. 1. Недостаточность обычных тестов 2. Тестирование на основе моделей 3.

    Сети Петри

  15. 1. Недостаточность обычных тестов 2. Тестирование на основе моделей 3.

    Сети Петри 4. Тестирование на основе сетей Петри
  16. 1. Недостаточность обычных тестов 2. Тестирование на основе моделей 3.

    Сети Петри 4. Тестирование на основе сетей Петри
  17. ОБЫЧНЫЙ ТЕСТ A A A 17

  18. ОБЫЧНЫЙ ТЕСТ Arrange: выполняет предусловия A A 18

  19. ОБЫЧНЫЙ ТЕСТ Arrange: выполняет предусловия Act: выполняет какое-то действие A

    19
  20. ОБЫЧНЫЙ ТЕСТ Arrange: выполняет предусловия Act: выполняет какое-то действие Assert:

    верифицирует состояние/поведение 20
  21. ОБЫЧНЫЙ ТЕСТ Arrange: выполняет предусловия Act: выполняет какое-то действие Assert:

    верифицирует состояние/поведение 21
  22. 22 class User < ApplicationRecord end

  23. 23 class User < ApplicationRecord end it 'destroys user’ do

    user = User.create! user.destroy expect(User.count).to eq(0) end
  24. 24 arrange act assert class User < ApplicationRecord end it

    'destroys user’ do user = User.create! user.destroy expect(User.count).to eq(0) end
  25. 25 class User < ApplicationRecord end it 'destroys user’ do

    user = User.create! user.destroy expect(User.count).to eq(0) end
  26. 26 class User < ApplicationRecord has_many :notes end class Note

    < ApplicationRecord belongs_to :user end it 'destroys user’ do user = User.create! user.destroy expect(User.count).to eq(0) end
  27. 27 class User < ApplicationRecord has_many :notes end class Note

    < ApplicationRecord belongs_to :user end it 'destroys user with a note’ do user = User.create!(note: Note.create!) user.destroy expect(User.count).to eq(0) end
  28. 28 class User < ApplicationRecord has_many :notes end class Note

    < ApplicationRecord belongs_to :user end it 'destroys user with a note’ do user = User.create!(note: Note.create!) user.destroy expect(User.count).to eq(0) end
  29. 29 class User < ApplicationRecord has_many :notes end class Note

    < ApplicationRecord belongs_to :user end ActiveRecord ::InvalidForeignKey: PG ::ForeignKeyViolation: ERROR: update or delete on table "users" violates foreign key constraint “fk_rails_83d9817008" on table "notes" DETAIL: Key (id)=(1) is still referenced from table “notes".
  30. 30 class User < ApplicationRecord has_many :notes, dependent: :destroy end

    class Note < ApplicationRecord belongs_to :user end it 'destroys user with a note’ do user = User.create!(note: Note.create!) user.destroy expect(User.count).to eq(0) end
  31. 31 class User < ApplicationRecord has_many :notes, dependent: :destroy end

    class Note < ApplicationRecord belongs_to :user end it 'destroys user with a note’ do user = User.create!(note: Note.create!) user.destroy expect(User.count).to eq(0) end
  32. КОМБИНАЦИИ СОСТОЯНИЙ 32

  33. 33 1.Писать больше тестов? КОМБИНАЦИИ СОСТОЯНИЙ

  34. 34 1.Писать больше тестов? 2.Рандомные данные? КОМБИНАЦИИ СОСТОЯНИЙ

  35. 1. Недостаточность обычных тестов 2. Тестирование на основе моделей 3.

    Сети Петри 4. Тестирование на основе сетей Петри
  36. ТЕСТИРОВАНИЕ НА ОСНОВЕ МОДЕЛЕЙ 1.Создаем модель системы
 
 36

  37. ТЕСТИРОВАНИЕ НА ОСНОВЕ МОДЕЛЕЙ 1.Создаем модель системы 2.Генерируем на основе

    модели тесты 37
  38. GRAPHWALKER 38

  39. yEd 39

  40. ПРИМЕР 40

  41. ПРИМЕР 41

  42. ПРИМЕР 42

  43. ПРИМЕР 43

  44. ПРИМЕР 44

  45. ПРИМЕР 45

  46. ПРИМЕР 46

  47. 47 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { }
  48. 48 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { }
  49. 49 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { }
  50. 50 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_GoToNewNoteView() { } }
  51. 51 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_GoToNewNoteView() { driver.pressKeyCode(AndroidKeyCode.KEYCODE_MENU); driver.findElementByClassName("android.widget.TextView").click(); } }
  52. 52 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_Discard() { driver.pressKeyCode(AndroidKeyCode.KEYCODE_MENU); driver.findElementByClassName("android.widget.TextView").click(); } }
  53. 53 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_Create() { } }
  54. 54 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_Create() { String noteName = "test+" + new Random().nextInt(); } }
  55. 55 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_Create() { String noteName = "test+" + new Random().nextInt(); driver.findElement(By.xpath(" //android.widget.EditText[1]")) .sendKeys(noteName); } }
  56. 56 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_Create() { String noteName = "test+" + new Random().nextInt(); driver.findElement(By.xpath(" //android.widget.EditText[1]")) .sendKeys(noteName); driver.hideKeyboard(); driver.pressKeyCode(AndroidKeyCode.KEYCODE_BACK); } }
  57. 57 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void e_Create() { String noteName = "test+" + new Random().nextInt(); driver.findElement(By.xpath(" //android.widget.EditText[1]")) .sendKeys(noteName); driver.hideKeyboard(); driver.pressKeyCode(AndroidKeyCode.KEYCODE_BACK); expectedNumberOfNotes ++; } }
  58. 58 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void v_NotesListView() { } }
  59. 59 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void v_NotesListView() { WebElement notesList = driver.findElementByClassName("android.widget.TextView"); assertTrue(notesList.getText().equals("Note pad”)); } }
  60. 60 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void v_NotesListView() { WebElement notesList = driver.findElementByClassName("android.widget.TextView"); assertTrue(notesList.getText().equals("Note pad”)); List<WebElement> notesInList = driver.findElement(By.className("android.widget.ListView")) .findElements(By.className("android.widget.TextView")); int actualNumberOfNotes = notesInList.size(); assertEquals(expectedNumberOfNotes, actualNumberOfNotes); } }
  61. 61 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void v_NewNoteView() { } }
  62. 62 @GraphWalker(value = "random(edge_coverage(100))", start = "v_NotesListView") public class NotesListTest

    { @Override public void v_NewNoteView() { WebElement notesEditor = driver.findElementByClassName("android.widget.EditText"); Assert.assertTrue(notesEditor.isDisplayed()); } }
  63. 63 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

  64. 64 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView
  65. 65 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView
  66. 66 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView
  67. 67 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Create After element e_Create
  68. 68 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Create After element e_Create Before element v_NotesListView After element v_NotesListView
  69. 69 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Create After element e_Create Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView
  70. 70 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Create After element e_Create Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView
  71. 71 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Create After element e_Create Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Discard After element e_Discard
  72. 72 $ mvn graphwalker:test [INFO] Tests: [INFO] NotesListTest(RandomPath, VertexCoverage, 100)

    Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Create After element e_Create Before element v_NotesListView After element v_NotesListView Before element e_GoToNewNoteView After element e_GoToNewNoteView Before element v_NewNoteView After element v_NewNoteView Before element e_Discard After element e_Discard Before element v_NotesListView After element v_NotesListView
  73. GRAPHWALKER 1.Java/Python 2.Конечные автоматы 73

  74. КОНЕЧНЫЙ АВТОМАТ 74

  75. КОНЕЧНЫЙ АВТОМАТ 75

  76. КОНЕЧНЫЙ АВТОМАТ 76

  77. КОНЕЧНЫЙ АВТОМАТ 77

  78. КОНЕЧНЫЙ АВТОМАТ 78

  79. КОНЕЧНЫЙ АВТОМАТ 79

  80. КОНЕЧНЫЙ АВТОМАТ 1.Дублирование 2.Concurrency = state explosion 80

  81. 1. Недостаточность обычных тестов 2. Тестирование на основе моделей 3.

    Сети Петри 4. Тестирование на основе сетей Петри
  82. СЕТЬ ПЕТРИ 82 not created Create User created

  83. СЕТЬ ПЕТРИ 83 позиции (places) хранят метки not created Create

    User created
  84. СЕТЬ ПЕТРИ 84 позиции (places) хранят метки переходы (transitions) перемещают

    метки not created Create User created
  85. СЕТЬ ПЕТРИ 85 позиции (places) хранят метки дуги связывают позиции

    и переходы переходы (transitions) перемещают метки not created Create User created
  86. СЕТЬ ПЕТРИ 86 позиция not created содержит метку not created

    Create User created
  87. СЕТЬ ПЕТРИ 87 переход Create User может сработать not created

    Create User created
  88. СЕТЬ ПЕТРИ 88 срабатывание удаляет метку из not created и

    добавляет в created not created Create User created
  89. 89 1. Переходы могут быть связаны только с позициями (и

    наоборот) СЕТЬ ПЕТРИ
  90. 90 1. Переходы могут быть связаны только с позициями (и

    наоборот) 2. Переход может сработать когда в каждой входной позиции есть по меньшей мере одна метка СЕТЬ ПЕТРИ
  91. 91 1. Переходы могут быть связаны только с позициями (и

    наоборот) 2. Переход может сработать когда в каждой входной позиции есть по меньшей мере одна метка 3. Срабатывание перехода забирает по одной метке из каждой входной позиции и добавляет по одной метке в каждую выходную позицию СЕТЬ ПЕТРИ
  92. not created Create User created СЕТЬ ПЕТРИ 92 ip allowed

  93. СЕТЬ ПЕТРИ 93 not created Create User created ip allowed

    not created Create User created ip allowed
  94. СЕТЬ ПЕТРИ 94 pending review not created Create User created

  95. СЕТЬ ПЕТРИ 95 pending review not created Create User created

    pending review not created Create User created
  96. СЕТЬ ПЕТРИ 96 not created Create User created

  97. СЕТЬ ПЕТРИ 97 not created Create User created not created

    Create User created
  98. КОНЕЧНЫЙ АВТОМАТ 98

  99. СЕТЬ ПЕТРИ 99 user not created user created note created

  100. СЕТЬ ПЕТРИ 100 user not created user created note created

    Create User
  101. СЕТЬ ПЕТРИ 101 user not created user created note created

    Create User Destroy User
  102. СЕТЬ ПЕТРИ 102 user not created user created note created

    Create User Destroy User Create Note
  103. СЕТЬ ПЕТРИ 103 user not created user created note created

    Create User Destroy User Create Note Destroy Note
  104. СЕТЬ ПЕТРИ 104 user not created user created note created

    Create User Destroy User Create Note Destroy Note
  105. СЕТЬ ПЕТРИ 105 user not created user created note created

    Create User Destroy User Create Note Destroy Note
  106. СЕТЬ ПЕТРИ 106 user not created user created note created

    Create User Destroy User Create Note Destroy Note
  107. КОНЕЧНЫЙ АВТОМАТ 107

  108. СЕТЬ ПЕТРИ 108 user not created user created note created

    Create User Destroy User Create Note Destroy Note post created
  109. СЕТЬ ПЕТРИ 109 user not created user created note created

    Create User Destroy User Create Note Destroy Note post created Create Post
  110. СЕТЬ ПЕТРИ 110 user not created user created note created

    Create User Destroy User Create Note Destroy Note post created Create Post Destroy Post
  111. КОНЕЧНЫЙ АВТОМАТ 111

  112. СЕТЬ ПЕТРИ 112 user not created user created note created

    Create User Destroy User Create Note Destroy Note post created Create Post Destroy Post video created
  113. СЕТЬ ПЕТРИ 113 user not created user created note created

    Create User Destroy User Create Note Destroy Note post created Create Post Destroy Post Create Video video created
  114. СЕТЬ ПЕТРИ 114 user not created user created note created

    Create User Destroy User Create Note Destroy Note post created Create Post Destroy Post Create Video Destroy Video video created
  115. 1. Недостаточность обычных тестов 2. Тестирование на основе моделей 3.

    Сети Петри 4. Тестирование на основе сетей Петри
  116. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ 116

  117. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ 1.Создаем модель системы используя cеть

    Петри
 
 117
  118. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ 1.Создаем модель системы используя cеть

    Петри 2.Генерируем на основе модели тесты 118
  119. СОЗДАНИЕ МОДЕЛИ 119

  120. СОЗДАНИЕ МОДЕЛИ 120 { "places": [ { "guid": "e57c0830-148f-11e8-bb7f-adf9986e1043", "identifier":

    "user created" } ], "transitions": [ { "guid": “df65a6e0-148f-11e8-bb7f-adf9986e1043" "identifier": "Create User", } ], "arcs": [ { "from_guid": "e57c0830-148f-11e8-bb7f-adf9986e1043", "to_guid": “df65a6e0-148f-11e8-bb7f-adf9986e1043" } ] }
  121. ЗАГРУЗКА СЕТИ 121

  122. ЗАГРУЗКА СЕТИ 122 class Node def input_arcs # ... end

    def output_arcs # ... end end
  123. ЗАГРУЗКА СЕТИ 123 class Node def input_arcs # ... end

    def output_arcs # ... end end class Place < Node end
  124. ЗАГРУЗКА СЕТИ 124 class Node def input_arcs # ... end

    def output_arcs # ... end end class Place < Node end class Transition < Node end
  125. ЗАГРУЗКА СЕТИ 125 class Node def input_arcs # ... end

    def output_arcs # ... end end class Place < Node end class Transition < Node end class Arc def from # ... end def to # ... end end
  126. ЗАГРУЗКА СЕТИ 126 class Runner def enabled?(transition) # ... end

    def fire(transition) # ... end def marking # ... end end
  127. СВЯЗЬ СЕТИ С ТЕСТОВЫМ КОДОМ 127

  128. СВЯЗЬ СЕТИ С ТЕСТОВЫМ КОДОМ 128 user not created user

    created note created Create User Destroy User Create Note Destroy Note
  129. 129 user not created user created note created Create User

    Destroy User Create Note Destroy Note class UserNoteNet < Rhizome ::Net end
  130. 130 user not created user created note created Create User

    Destroy User Create Note Destroy Note class UserNoteNet < Rhizome ::Net runner { Runner.new('user-note.bpf', marking: ['user not created']) } end
  131. 131 class UserNoteNet < Rhizome ::Net runner { Runner.new('user-note.bpf', marking:

    ['user not created']) } transition('Create User') { @user = User.create! } transition('Destroy User') { @user.destroy } end user not created user created note created Create User Destroy User Create Note Destroy Note
  132. 132 class UserNoteNet < Rhizome ::Net runner { Runner.new('user-note.bpf', marking:

    ['user not created']) } transition('Create User') { @user = User.create! } transition('Destroy User') { @user.destroy } transition('Create Note') { @note = Note.create!(user: @user) } transition('Destroy Note') { @note.destroy } end user not created user created note created Create User Destroy User Create Note Destroy Note
  133. 133 class UserNoteNet < Rhizome ::Net runner { Runner.new('user-note.bpf', marking:

    ['user not created']) } transition('Create User') { @user = User.create! } transition('Destroy User') { @user.destroy } transition('Create Note') { @note = Note.create!(user: @user) } transition('Destroy Note') { @note.destroy } place('user not created') do empty { expect(User.count).to be > 0 } filled { expect(User.count).to eq(0) } end end user not created user created note created Create User Destroy User Create Note Destroy Note
  134. 134 class UserNoteNet < Rhizome ::Net runner { Runner.new('user-note.bpf', marking:

    ['user not created']) } transition('Create User') { @user = User.create! } transition('Destroy User') { @user.destroy } transition('Create Note') { @note = Note.create!(user: @user) } transition('Destroy Note') { @note.destroy } place('user not created') do empty { expect(User.count).to be > 0 } filled { expect(User.count).to eq(0) } end place('user created') do empty { expect(User.count).to eq(0) } filled { expect(User.count).to be > 0 } end end user not created user created note created Create User Destroy User Create Note Destroy Note
  135. class UserNoteNet < Rhizome ::Net runner { Runner.new('user-note.bpf', marking: ['user

    not created']) } transition('Create User') { @user = User.create! } transition('Destroy User') { @user.destroy } transition('Create Note') { @note = Note.create!(user: @user) } transition('Destroy Note') { @note.destroy } place('user not created') do empty { expect(User.count).to be > 0 } filled { expect(User.count).to eq(0) } end place('user created') do empty { expect(User.count).to eq(0) } filled { expect(User.count).to be > 0 } end place('note created') do empty { expect(Note.count).to eq(0) } filled { expect(Note.count).to be > 0 } end end user not created user created note created Create User Destroy User Create Note Destroy Note 135
  136. ОБХОД СЕТИ 1. Даем каждому переходу одинаковую вероятность (4 перехода

    = 0,25 каждому) 136
  137. ОБХОД СЕТИ 1. Даем каждому переходу одинаковую вероятность (4 перехода

    = 0,25 каждому) 2. Генерируем случайное число - порог вероятности выбора перехода 137
  138. ОБХОД СЕТИ 1. Даем каждому переходу одинаковую вероятность (4 перехода

    = 0,25 каждому) 2. Генерируем случайное число - порог вероятности выбора перехода 3. Выбираем первый переход с подходящей под порог вероятностью, который может сработать 138
  139. ОБХОД СЕТИ 1. Даем каждому переходу одинаковую вероятность (4 перехода

    = 0,25 каждому) 2. Генерируем случайное число - порог вероятности выбора перехода 3. Выбираем первый переход с подходящей под порог вероятностью, который может сработать 4. Срабатываем переход 139
  140. ОБХОД СЕТИ 1. Даем каждому переходу одинаковую вероятность (4 перехода

    = 0,25 каждому) 2. Генерируем случайное число - порог вероятности выбора перехода 3. Выбираем первый переход с подходящей под порог вероятностью, который может сработать 4. Срабатываем переход 5. Проверяем пустые и заполненные позиции 140
  141. ОБХОД СЕТИ 1. Даем каждому переходу одинаковую вероятность (4 перехода

    = 0,25 каждому) 2. Генерируем случайное число - порог вероятности выбора перехода 3. Выбираем первый переход с подходящей под порог вероятностью, который может сработать 4. Срабатываем переход 5. Проверяем пустые и заполненные позиции 6. Уменьшаем вероятность сработанного перехода в 2 раза 141
  142. ОБХОД СЕТИ 1. Даем каждому переходу одинаковую вероятность (4 перехода

    = 0,25 каждому) 2. Генерируем случайное число - порог вероятности выбора перехода 3. Выбираем первый переход с подходящей под порог вероятностью, который может сработать 4. Срабатываем переход 5. Проверяем пустые и заполненные позиции 6. Уменьшаем вероятность сработанного перехода в 2 раза 7. Если все переходы сработали хотя бы раз, останавливаемся. Если нет, повторяем с пункта 2 142
  143. 143 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created
  144. 144 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note
  145. 145 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Create Note New marking: user created, note created Transitions left: Destroy User, Destroy Note
  146. 146 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Create Note New marking: user created, note created Transitions left: Destroy User, Destroy Note Executing Destroy Note New marking: user created Transitions left: Destroy User
  147. 147 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Create Note New marking: user created, note created Transitions left: Destroy User, Destroy Note Executing Destroy Note New marking: user created Transitions left: Destroy User Executing Destroy User New marking: user not created Finished traversing user_note net.
  148. 148 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created
  149. 149 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note
  150. 150 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Destroy User New marking: user not created Transitions left: Create Note, Destroy Note
  151. 151 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Destroy User New marking: user not created Transitions left: Create Note, Destroy Note Executing Create User New marking: user created Transitions left: Create Note, Destroy Note
  152. 152 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Destroy User New marking: user not created Transitions left: Create Note, Destroy Note Executing Create User New marking: user created Transitions left: Create Note, Destroy Note Executing Create Note New marking: user created, note created Transitions left: Destroy Note
  153. 153 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Destroy User New marking: user not created Transitions left: Create Note, Destroy Note Executing Create User New marking: user created Transitions left: Create Note, Destroy Note Executing Create Note New marking: user created, note created Transitions left: Destroy Note Executing Destroy Note New marking: user created Finished traversing user_note net.
  154. 154 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created
  155. 155 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note
  156. 156 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Create Note New marking: user created, note created Transitions left: Destroy User, Destroy Note
  157. 157 $ bin/rhizome Traversing user_note net: Initial marking: user not

    created Executing Create User New marking: user created Transitions left: Destroy User, Create Note, Destroy Note Executing Create Note New marking: user created, note created Transitions left: Destroy User, Destroy Note Executing Destroy User 
 ActiveRecord ::InvalidForeignKey: PG ::ForeignKeyViolation: ERROR: update or delete on table "users" violates foreign key constraint "fk_rails_83d9817008" on table "notes" DETAIL: Key (id)=(1) is still referenced from table “notes".
  158. RHIZOME 1. Воспроизводимость тестов с помощью seed 158

  159. RHIZOME 1. Воспроизводимость тестов с помощью seed 2. Параллелизация как

    у любого другого фреймворка 159
  160. RHIZOME 1. Воспроизводимость тестов с помощью seed 2. Параллелизация как

    у любого другого фреймворка 3. Фреймворк общего назначения (хоть с Selenium) 160
  161. ОБЫЧНЫЙ ТЕСТ (RSPEC) 161 RHIZOME

  162. ОБЫЧНЫЙ ТЕСТ (RSPEC) RHIZOME 1000 LoC 162 100 LoC

  163. ОБЫЧНЫЙ ТЕСТ (RSPEC) RHIZOME 1000 LoC 1m 163 100 LoC

    1m
  164. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ 1. Тестовое покрытие увеличилось
 


    
 
 164
  165. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ 1. Тестовое покрытие увеличилось 2.

    Время выполнения тестов осталось прежним
 
 165
  166. ТЕСТИРОВАНИЕ НА ОСНОВЕ СЕТЕЙ ПЕТРИ 1. Тестовое покрытие увеличилось 2.

    Время выполнения тестов осталось прежним 3. Время на написание/поддержку тестов сократилось 166
  167. P.S. Что еще?

  168. 168 user not created user created note created Create User

    Destroy User Create Note Destroy Note
  169. 169 user not created user created note created Create User

    Destroy User Create Note Destroy Note
  170. 170 user not created user created note created Create User

    Destroy User Create Note Destroy Note
  171. 171 user not created user created note created Create User

    Destroy User Create Note Destroy Note
  172. 172 user not created user created note created Create User

    Destroy User Create Note Destroy Note
  173. RESET ARC 173 user not created user created note created

    Create User Destroy User Create Note Destroy Note очищает позицию после срабатывания
  174. INHIBITOR ARC 174 user created note created Create User Destroy

    User Create Note Destroy Note разрешает срабатывание перехода только если в позиции нет меток
  175. БЕЗОПАСНЫЕ СЕТИ ПЕТРИ 175 user not created user created note

    created Create User Destroy User Create Note Destroy Note не больше одной метки в позиции
  176. ОБЫЧНЫЕ СЕТИ ПЕТРИ 176 user not created user created note

    created Create User Destroy User Create Note Destroy Note
  177. ЦВЕТНЫЕ СЕТИ ПЕТРИ 177 user not created user created note

    created Create User Destroy User Create Note Destroy Note метка хранит данные
  178. ARC GUARD 178 user not created user created note created

    Create User Destroy User Create Note Destroy Note разрешает срабатывание перехода только если guard = true user is admin
  179. user not created user created Create User Destroy User ИЕРАРХИЧЕСКИЕ

    СЕТИ ПЕТРИ 179 Note note created Create Note Destroy Note
  180. ОТЛОЖЕННЫЕ ПЕРЕХОДЫ ВРЕМЕННЫЕ СЕТИ ПЕТРИ СТОХАСТИЧЕСКИЕ СЕТИ ПЕТРИ АЛГОРИТМЫ ДЛЯ

    АНАЛИЗА … 180
  181. # Лёша Родионов @p0deje