Phantomjs i jquery datatables, testowanie

Witam
Używam http://www.datatables.net/ a do testów phantomjs(poltergeist). Dodałem sobie taki helper:

def wait_for_datatable_processing
page.should have_selector ‘div’, text: “Processing…”, visible: true
page.should have_selector ‘div’, text: “Processing…”, visible: false
end

Służy on do tego aby sprawdzać czy dane tabeli sie ajaxowo odświeżyły.
Przykładowy test:

[code=ruby] it ‘should filter members’ do
other = create :member
filtered = create :member, name: ‘Filter’

  visit members_path

  within '#members_list_filter' do
    fill_in 'Search', with: 'Filter'
  end

  wait_for_datatable_processing

  within('table#members_list') do
    expect(page).to have_content filtered.name
    expect(page).not_to have_content other.name
  end
end[/code]

Test ten jest bardzo wolny i o ile na mojej maszynie przechodzi to na kolegi już nie. Czy można to jakoś uprościć ewentualnie jakieś inne podejście ?

Nie jestem tego pewien, ale możliwe jest, że możesz tu mieć race condition. Kiedy ten kod będzie wykonywany ‘page.should have_selector ‘div’, text: “Processing…”, visible: true’ w przeglądarce tekst “Processing…” może (ale nie musi) być już widoczny.

Ja żeby testować datatables tylko testuje w integracji fakt, że działają. A szukanie i filtrowanie testuje na poziomie controllera (czy json w odpowiednim formacie został zwrócony).

[code] #integration test
it ‘should populate table with members’ do
member = create :member

within('table#members_list') do
  expect(page).to have_content member.name
end

end[/code]

[code]

controller test

before do
create(:member, name: ‘foo’)
create(:member, name: ‘bar’)
create(:member, name: ‘baz’)
end

it ‘returns 2 rows without “foo”’ do
get :index, params(format: :json, sSearch: “ba”, iDisplayStart: ‘0’, iDisplayLength: ‘25’)
body = response.body
body.should_not include ‘foo’
ActiveSupport::JSON.decode(body)[‘aaData’].count.should == 2
end[/code]
Oczywiście na poziomie controllera zamiast stworzyć rekordy w bazie możesz je po prostu zmokować. Ale ja mam dosyć skomplikowany kod który filtruje, stronicuje i zwraca odpowiedni json. Stąd wolę przetestować wszystko.

Dzięki. Wolałbym jednak testować to w testach funkcjonalnych, czasem drobna zmiana w js może spowowodować że tabele sie nie pokażą, mimo że json jest zwracany. Problemem tu jest phantomjs który jeszcze nie ze wszystkim radzi sobie idealnie.

To czekaj jakiego DataSource używasz w Datatables? DOM czy ajax?

Ajax.
Samo wyświetlanie rekordów zaraz po wejściu na strone działa ok i testuje sie poprawnie.
Problem jest w tym że czasem phantomjs/capybara (?) nie czeka aż dane się załadują, np po sortowaniu lub wyszukiwaniu rekordu i od razu chce sprawdzać czy tekst istnieje, czasem test przechodzi a czasem nie, losowo. Przykładowy test

[code=ruby] it ‘should filter members’ do
other = create :member
filtered = create :member, name: ‘Filter’

  visit members_path

  within '#members_list_filter' do
    fill_in 'Search', with: 'Filter'
  end

  wait_for_datatable_processing # mój helper

  within('table#members_list') do
    expect(page).to have_content filtered.name
    expect(page).not_to have_content other.name
  end
end[/code]

https://github.com/jnicklas/capybara#asynchronous-javascript-ajax-and-friends. Capybara powinna czekać na “should have_content” i “should_not have_content”. W którym dokładnie miejscu test czasem się wywala?

Co do testu integracyjne, ten który podałem moim zdaniem jest wystarczający. On po prostu sprawdza czy Datatables załadowało do tabeli dane z serwera. A to czy Datatables te dane posortuje i pofiltruje jest już jego właściwą funkcjonalność, która zostało przetestowana przez autora biblioteki i zakładasz, że działa.

Tak jak mówi asok, na oko masz race condition, jeżeli na komputerze kolegi ajax wykona się szybciej niż pierwsza linijka helpera to test nie przejdzie, z informacją, że nie nie może znaleść div’a z tekstem “Processing…”

def wait_for_datatable_processing
page.should have_selector ‘div’, text: “Processing…”, visible: true
page.should have_selector ‘div’, text: “Processing…”, visible: false
end

Kombinuje z czymś takim. Dodałem callbacki do coffescriptu dla datatables:

fnPreDrawCallback: -> $(this).removeAttr('draw-finished') fnDrawCallback: -> $(this).attr('draw-finished', true)
i sprawdzam w teście czy atrybut sie ustawił:

expect(page).to have_xpath "//table[@id = 'members_list' and @draw-finished = 'true']"

Niestety test wykonuje sie jakies 20 sekund, podobnie jak poprzednia wersja, czyli zdecydowanie za długo.
Odbiegając trochę od głównego tematu które wyszukiwanie w testach jest najszybsze ? have_xpath, have_css a może coś innego ?