Статьи

Движущиеся картинки с Синатрой, часть II

mp_sinatra

В части I мы создали сайт Sinatra для чтения изображений из каталога. Теперь мы собираемся создать форму для загрузки изображений вместе с тестами, чтобы убедиться, что она работает.

Для этого вам понадобится форма с вводом файла. Давайте напишем тест, чтобы убедиться, что это произойдет.

Тест / test.rb

...
def test_for_upload_form
  get '/upload'
  assert last_response.ok?
  assert last_response.body.include?("type=\"file\"")
end
...

Этот тест проверяет, что одним из входных данных формы будет тип «файл». Это еще не так, поэтому тест должен провалиться.

 $ ruby test/test.rb
Run options: --seed 34613

# Running tests:

..F

Finished tests in 0.022114s, 135.6607 tests/s, 180.8809 assertions/s.

  1) Failure:
test_for_upload_form(MyTest) [test/test.rb:27]:
Failed assertion, no message given.

3 tests, 4 assertions, 1 failures, 0 errors, 0 skips

Моя линия 27

 assert last_response.ok?

Если вам интересно, запустите приложение и перейдите на страницу / загрузки .

тр-GET-загрузка

Похоже, нам нужен обработчик маршрута для загрузки. Добавьте это в файл main.rb.

main.rb

 get '/upload' do
  "Hello World"
end

Как вы думаете, тест пройдет или не пройдет? Запустите его и узнайте.

 $ ruby test/test.rb
Run options: --seed 10631

# Running tests:

F..

Finished tests in 0.022114s, 135.6607 tests/s, 226.1011 assertions/s.

  1) Failure:
test_for_upload_form(MyTest) [test/test.rb:28]:
Failed assertion, no message given.

3 tests, 5 assertions, 1 failures, 0 errors, 0 skips

Предыдущая ошибка исчезла, но теперь появилась новая. У нас нет формы для этой страницы.

main.rb

 ...
get '/upload' do
  erb :upload
end
...
@@upload
<!DOCTYPE html>
<html>
  <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="user-scalable=yes, width=device-width" />
<title>Upload Moving Pictures</title>
</head>
<body>
  <form action="/upload" enctype="multipart/form-data" method="post">
    <label for="file">File to upload:</label>
    <input id="file" type="file" name="file">
    <input id="submit" type="submit" name="submit" value="Upload picture!">
  </form>
</body>
</html>
...

Если вы помните, мы используем удобные встроенные представления Синатры. Теперь, когда у нас есть форма, которая позволит нам загрузить фотографию, вы думаете, тест пройдет на этот раз?

 $ ruby test/test.rb
Run options: --seed 6047

# Running tests:

...

Finished tests in 0.022980s, 130.5483 tests/s, 217.5805 assertions/s.

3 tests, 5 assertions, 0 failures, 0 errors, 0 skips

У вас есть страница загрузки и форма, которая имеет возможность выбрать файл. Какой следующий шаг? Да, загрузите файл в каталог public / slideshow_pictures . Давайте напишем тест, который опубликует наш новый обработчик маршрута загрузки и сообщит, что загрузка произошла.

Тест / test.rb

 ...
def test_upload_file
  post '/upload'
  assert last_response.ok?
  assert last_response.body.include?("Uploaded")
end
...

Запустите тест.

 $ ruby test/test.rb
Run options: --seed 59047

# Running tests:

...F

Finished tests in 0.023828s, 167.8697 tests/s, 251.8046 assertions/s.

  1) Failure:
test_upload_file(MyTest) [test/test.rb:33]:
Failed assertion, no message given.

4 tests, 6 assertions, 1 failures, 0 errors, 0 skips

Ответ был не в порядке. Просто из любопытства иди и запусти сервер

 $ ruby main.rb

Перейти на страницу загрузки. и отправьте форму. Вот что приложение дало мне:
тр-пост-загрузка
Это предлагает текст в файл main.rb, но давайте изменим «Hello World» на «Uploaded».

main.rb

 post "/upload" do
  "Uploaded."
end

Запустите тест. Это прошло? Здорово. Поздравляем, мы только что написали ужасный тест. Имя теста — test_upload_file. , но мы даже не проверяли, было ли загружено что-нибудь. Как бы вы проверили это?

Вы можете посчитать количество файлов в каталоге slideshow_picture . Загрузите файл и проверьте, увеличилось ли количество файлов на один. Давайте перепишем тест.

Тест / test.rb

 ...
def test_upload_file
  pictures_before = load_pictures.length
  post '/upload'
  pictures_after = load_pictures.length
  assert_equal (pictures_before + 1), pictures_after
end
...

Давайте попробуем это. Запустите тест.

 $ ruby test/test.rb
Run options: --seed 51246

# Running tests:

..F.

Finished tests in 0.030883s, 129.5211 tests/s, 194.2816 assertions/s.

  1) Failure:
test_upload_file(MyTest) [test/test.rb:35]:
Expected: 2
  Actual: 1

4 tests, 6 assertions, 1 failures, 0 errors, 0 skips

Лучше. Это не должно быть тестом на лету. У нас нет кода для загрузки файла в обработчике маршрута post '/upload' Давайте добавим это.

main.rb

 post "/upload" do 
  File.open('public/slideshow_pictures/' + params['file'][:filename], "w") do |f|
    f.write(params['file'][:tempfile].read)
  end
  "Uploaded."
end

Здесь мы берем файл из формы, open Думаешь тест пройдёт сейчас? У нас есть код для записи файла. Запустите его и посмотрите.

 $ ruby test/test.rb
Run options: --seed 51246

# Running tests:

..F.

Finished tests in 0.030883s, 129.5211 tests/s, 194.2816 assertions/s.

  1) Failure:
test_upload_file(MyTest) [test/test.rb:35]:
Expected: 2
  Actual: 1

4 tests, 6 assertions, 1 failures, 0 errors, 0 skips

Что произошло? Мы разместили метод загрузки. Подождите, мы отправили файл? Нам нужно отправить файл param для загрузки метода.

test.rb

 ...
post '/upload', {:file =>{:filename=>"cat.jpg"}}
...

Это создаст пустой файл с именем cat.jpg Как насчет этого времени … пройдет тест?

 $ ruby test/test.rb
Run options: --seed 42496

# Running tests:

....

Finished tests in 0.078357s, 51.0484 tests/s, 76.5726 assertions/s.

4 tests, 6 assertions, 0 failures, 0 errors, 0 skips

Сладкий. Король мира!
Просто для удовольствия, давайте снова проведем тест и посмотрим на удивительность.

 $ ruby test/test.rb
Run options: --seed 25680

# Running tests:

F...

Finished tests in 0.083972s, 47.6349 tests/s, 71.4524 assertions/s.

  1) Failure:
test_upload_file(MyTest) [test/test.rb:35]:
Expected: 3
  Actual: 2

4 tests, 6 assertions, 1 failures, 0 errors, 0 skips

Теперь это как прощание с королями! Что произошло? Если вы посмотрите в каталог public / slideshow_pictures , то уже есть cat.jpg . Мы просто переписываем его, когда загружаем в тест другой файл cat.jpg . Это означает, что мы не увеличиваем количество файлов, поэтому тест не пройден.
Как бы вы удалили этот файл? Один из вариантов — посмотреть, существует ли файл . Если это произойдет, удалите его.

Тест / test.rb

 ...
def test_upload_file
  if File.exists?("public/slideshow_pictures/cat.jpg")
    File.delete("public/slideshow_pictures/cat.jpg")
  end
  pictures_before = load_pictures.length
  post '/upload', {:file =>{:filename=>"cat.jpg"}}
  pictures_after = load_pictures.length
  assert_equal (pictures_before + 1), pictures_after
end
...

Перезапустите тест.

 $ ruby test/test.rb
Run options: --seed 12414

# Running tests:

....

Finished tests in 0.069093s, 57.8930 tests/s, 86.8395 assertions/s.

4 tests, 6 assertions, 0 failures, 0 errors, 0 skips

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

Давайте рассмотрим, что мы сделали.

  • Мы написали и теперь можем распознать бесполезный тест.
  • Мы научились видеть, существуют ли файлы.
  • Мы узнали, как удалять файлы.

В следующей (и последней) статье этой серии мы добавим немного CSS, проверим конкретные типы файлов и завершим наше основное приложение для отображения изображений.