RubyonRails教程第三版,第11章,练习3,测试图像上传器



指令如下:

按照清单11.68中的模板,在第11.4节中编写一个图像上传器的测试。作为准备,您应该向fixtures目录中添加一个映像(例如,使用cp-app/assets/images/rails.png-test/gfixtures/)。(如果您使用的是Git,我还建议您更新.gitignore文件,如清单11.69所示。)为了避免出现混淆错误,您还需要配置CarrierWave,通过创建如清单11.70所示的初始化器文件来跳过测试中的图像大小调整。清单11.68中的附加断言检查了主页上的文件上传字段和微柱上由有效提交产生的有效图像属性。注意使用特殊的fixture_file_pload方法将文件作为测试中的固定装置上传。22提示:要检查有效的图片属性,请使用第10.1.4节中提到的assigns方法在有效提交后访问创建操作中的微post。

这是我在test/integration/micrposts_interface_test.rb 中的代码

test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'div.pagination'
assert_select 'input[type=FILL_IN]'
# Invalid submission
assert_no_difference 'Micropost.count' do
post microposts_path, micropost: { content: "" }
end
assert_select 'div#error_explanation'
# Valid submission
content = "This micropost really ties the room together"
picture = fixture_file_upload('test/fixtures/rails.png', 'image/png')
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: FILL_IN }
end
assert FILL_IN.picture?
follow_redirect!
assert_match content, response.body
# Delete a post.
assert_select 'a', text: 'delete'
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference 'Micropost.count', -1 do
delete micropost_path(first_micropost)
end
# Visit a different user.
get user_path(users(:archer))
assert_select 'a', text: 'delete', count: 0
end

在assert_select"input[type=FILL_In]"中,我的填充是type=file

在post microposts_path中,micropost:{content:content,picture:FILL_In},我填写的是picture:true

在断言FILL_In.picture中?是@user.microposts.picture吗?

我得到的错误是:NoMethodError:NoMethodError:未定义的方法`picture?'对于#

所以我认为我的前两个FILL_IN是正确的。问题来自第三次填写。我写了@user.microposts,因为我想测试是否有图片?,它必须在用户的微柱上。但错误是没有办法拍照?

我也试过@user.micpost.picture?,错误为NoMethodError:NoMethodError:#的未定义方法"micropost">

我认为我的推理是正确的,但显然不是。帮助我完全是个新手。

我的解决方案似乎有效:

test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'div.pagination'
assert_select 'input[type=file]'
# Invalid submission
assert_no_difference 'Micropost.count' do
post microposts_path, micropost: { content: "" }
end
assert_select 'div#error_explanation'
# Valid submission
content = "This micropost really ties the room together"
picture = fixture_file_upload('test/fixtures/sample-image.jpg', 'image/jpg')
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: picture }
end
assert assigns(:micropost).picture?
assert_redirected_to root_url
follow_redirect!
assert_match content, response.body
# Delete a post.
assert_select 'a', text: 'delete'
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference 'Micropost.count', -1 do
delete micropost_path(first_micropost)
end
# Visit a different user.
get user_path(users(:archer))
assert_select 'a', text: 'delete', count: 0
end

回答这个问题有点晚,但也许这会帮助其他人。我分别给出了长答案和短答案,如果你想快速解释,请阅读问题末尾的TLDR,如果你想要更多解释,请随时阅读全文:)

1)assert_select"input[type=FILL_IN]">

使用file或"file"将通过测试。根据assert_select here:link上的文档,"选择器可以是CSS选择器表达式(String)、具有替换值的表达式或HTML::selector对象。"本质上,它只需要是一个有效的CSS选择器,根据这个stackoverflow post:link,根据情况(如果它是字母数字字符串,通常不需要,就像这里的情况一样),它可能需要引号,也可能不需要引号,但通常使用引号是很好的做法,这样就不会出现混淆/错误。

TLDR:在这种情况下,使用'input[type="file"]'或'input[type=file]'都可以,但使用引号通常被认为是避免错误的好方法

2)post microposts_path,micropost:{content:content,picture:FILL_IN}

对于这个,正如@Nick所提到的,您可能只想使用在具有assert_difference的行上方的行上创建的变量"picture"。请记住,当您将图片属性添加到微柱模型时,您运行了以下命令:

rails generate migration add_picture_to_microposts picture:string

这意味着它希望您在创建微支柱时传递一个字符串,而不是布尔值。还要注意测试实际在做什么:

assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: FILL_IN }
end

该代码实际上是通过张贴到microposts路径来创建一个micropost,然后检查以确保计数增加1。

现在,您可能会说:但是picture变量不是字符串!这是真的,我不是CarrierWave的专家,我也没有真正深入研究它的代码,但它似乎实际上需要一个文件路径和MIME(文件扩展名)类型,基于fixture_file_upload的文档,可以在这里找到:链接。如果你还记得教程中的内容,你添加了一行:

mount_uploader :picture, PictureUploader

将图片属性与PictureUploader类(位于app/uploloaders/picture_uploader.rb中)相关联,该类在类文件中具有以下内容:

class PictureUploader < CarrierWave::Uploader::Base

这意味着它继承了CarrierWave::Uploader::基类,这可能意味着CarrierWave正在扰乱picture属性,以获取字符串以外的内容(正如我所提到的,它似乎采用了基于文档的路径和MIME类型),但布尔值不起作用。(为了记录在案,我做了一些测试,先传递了一个随机字符串,然后又传递了一条随机文件路径,但都像预期的那样失败了——传递布尔值也是如此)。

此外,无可否认,这是一个小细节,但即使传入布尔值有效,它也只能测试它是否是一张图片,而不是一张特定的图片,这将是使用图片变量的另一个参数。

TLDR:您可能只应该使用图片变量:post-micposts_path,micropost:{content:content,picture:picture}

3)断言FILL_IN.picture

你提到你使用了代码:

@user.microposts.picture?

得到了一个NoMethodError。原因是@user.microposts将返回一组微帖子,而不是单个微帖子,所以它很困惑(特别是,它返回了一个ActiveRecord_Associations_CollectionProxy,它没有picture?方法,因此,你会得到一个NoMethodError。此外,别忘了,你可以打开rails控制台,运行User.first.microposts.class来了解@User.micposts返回的对象是什么类型的)。还记得那张图片吗?这个方法只适用于一个单独的微柱,所以你们会想做一些类似的事情:

@user.microposts.first.picture?

它将检查最近创建的微柱(微柱按创建日期/时间排序,最近的是第一个)以获取图片。

然而,还有另一种方法可以做到这一点,它使用Hartl在练习中给出的提示:"要检查有效的图片属性,请使用第10.1.4节中提到的assigns方法,在有效提交后访问创建操作中的微柱">

如果您还记得,您可以使用assigns方法从控制器访问实例变量。microposts控制器中的创建操作有一个实例变量@micpost,它也将是用户创建的最新的micropost。

代码看起来像:

foo = assigns(:micropost)
assert foo.picture?

事实上,通过添加以下代码,您可以向自己证明这两种方法都可以工作:

foo = assigns(:micropost)
assert foo.picture?
assert @user.microposts.first.picture?
assert_equal foo, @user.microposts.first

因此,这段代码的作用如下:首先,它创建一个变量foo,并将新创建的micropost分配给它。然后,它检查foo.picture?是真的,然后检查另一个方法@user.microposts.first.picture?并检查它是否也是真的。最后,它检查foo和@user的最新微post是否相同,并且所有这些测试都应该通过

TLDR:你在调用图片?方法是在一组微柱上,而不是单个微柱上。您可以使用@user.microposts.first.picture?或者,如果您想使用assigns()方法,您也可以使用它,并使用以下内容:

foo = assigns(:micropost)
assert foo.picture?

希望能有所帮助!

我认为第一个FILL_IN应该读取type="file"以检查这样的输入是否可用。

对于第二个FILL_IN,我认为解决方案是{ content: content, picture: picture },其中最后一个"picture"指的是上面的两行(定义该变量的地方)。

第三部和最后一部电影我不确定。考虑到Hartl提供的提示,我认为应该是:

plaatje = assigns(:micropost)
assert plaatje.picture?

但我也是一个新手,并遵循教程,所以我可能错了。如果有效,请告诉我。

有了这些解决方案,完整的代码是:

test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'div.pagination'
assert_select 'input[type="file"]'
# Invalid submission
assert_no_difference 'Micropost.count' do
post microposts_path, micropost: { content: "" }
end
assert_select 'div#error_explanation'
# Valid submission
content = "This micropost really ties the room together"
pict = fixture_file_upload('test/fixtures/rails.png', 'image/png')
assert_difference 'Micropost.count', 1 do
post microposts_path, micropost: { content: content, picture: pict }
end
plaatje = assigns(:micropost)
assert plaatje.picture?
assert_redirected_to root_url
follow_redirect!
assert_match content, response.body
# Delete a post.
assert_select 'a', text: 'delete'
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference 'Micropost.count', -1 do
delete micropost_path(first_micropost)
end
# Visit a different user.
get user_path(users(:archer))
assert_select 'a', text: 'delete', count: 0
end

第三个FILL_IN实际上可以使用以下方式填写:@user.microposts.first.picture?您的第一个解决方案不起作用,因为您必须指定要查询的微邮政。

最新更新