Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

InoAyaka / 課題2 #12

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions kadai2/InoAyaka/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# <課題2>【TRY】io.Readerとio.Writer
## 概要
### io.Readerとio.Writerについて調べてみよう

- 標準パッケージでどのように使われているか
- io.Readerとio.Writerがあることで、どういう利点があるのか具体例を挙げて考えてみる

### 調べてみた結果

<details>
<summary>長くなってしまったため、折りたたみ</summary>

#### io.Readerとは
なんらかのバイト列の入力を抽象化するための基本的なインタフェース
メソッドには、Read()が定義されている

#### io.Writerとは
なんらかのバイト列の出力を抽象化するための基本的なインタフェース
メソッドには、Write()が定義されている

#### io.Reader、io.Writerを実装している標準パッケージ
方法)godoc -analysis=type で確認
※goModuleモードは対応していないため、一時GOPATHモードにして実施>

os.File
pipe
bytes.Buffer などなど

#### 標準パッケージでどのように使っているか
os.File はReadとWriteを実装している
func (f *File) Read(b []byte) (n int, err error)
func (f *File) Write(b []byte) (n int, err error)
→ io.Readerまたはio.Writerを引数に指定している関数にos.Fileを渡すことができる


#### どういう利点があるのか
標準入力、標準出力、ファイル、ネットワーク、その他さまざまな入力処理、出力処理において
io.Reader、io.Writerという共通の型で扱うことができる → 共通化が実現できる

例えば、標準入出力、ファイル、ネットワークなんに関しても同じような処理を行う場合には、
引数にio.Readerもしくはio.Writer を指定してあげると良い


また、io.Writer、io.Readerがさまざまな入出力を共通化しているので、
テスト等により出力先を一時的に変えたいといった場合にも、以下のように変更することができる

``` 例
//この変数outをtestファイルで上書きする
var out io.Writer = os.Stdout
fmt.Fprintln(out,string.Join(args,sep))
```
</details>



# <課題2>【TRY】テストを書いてみよう
## 概要
### 1回目の課題のテストを作ってみて下さい

- テストのしやすさを考えてリファクタリングしてみる
- テストのカバレッジを取ってみる
- テーブル駆動テストを行う
- テストヘルパーを作ってみる

### 動作手順
```
$ go test ./...

# HTMLにカバレッジを保存する場合
$ go test -coverprofile=cover.out ./...
$ go tool cover -html=cover.out -o cover.html
```

### カバレッジ
[cover.html](https://github.com/gopherdojo/dojo8/blob/kadai2-InoAyaka/kadai2/InoAyaka/cover.html) 参照


##### 補足事項
(testdataディレクトリ配下に入っているテスト用イメージについて)
オリジナルのThe Go gopher(Gopherくん)は、Renée Frenchによってデザインされました。


### 感想
- カバレッジをあげるために、どのように工夫すればいいのか試行錯誤といった感じでした
- テストヘルパーについても、正直もう少しスッキリとした形にできるのではないか...といった感じになってしまいました
- テスト全般において、他の方のコードも参考にもっと勉強が必要だなと強く感じました

78 changes: 78 additions & 0 deletions kadai2/InoAyaka/converter/converter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//Package converter は指定されたパスに対し、画像変換を行います。
//(対応形式:jpg,png,gif,bmp,tiff)
package converter

import (
"fmt"
"image"
"image/gif"
"image/jpeg"
"image/png"
"os"
"regexp"
"strings"

"golang.org/x/image/bmp"
"golang.org/x/image/tiff"
)

//Args ImageConverter()を使う際に指定が必要となる引数
type Args struct {
FilePath string //変換対象となるファイル名
BeforeFormat string //変換前 画像形式
AfterFormat string //変換後 画像形式
}

//ImageConverter 指定した画像形式に変換を行います。
func ImageConverter(a Args) error {

f, err := os.Open(a.FilePath)
if err != nil {
return fmt.Errorf("%s", err)
}
defer f.Close()

//ファイルオブジェクトを画像オブジェクトに変換
img, _, err := image.Decode(f)
if err != nil {
return fmt.Errorf("%w : %s", err, f.Name())
}

//変換後のファイルパス
rep := regexp.MustCompile("(?i)" + a.BeforeFormat + "$")
outFilePath := rep.ReplaceAllString(f.Name(), a.AfterFormat)

//変換後ファイルの新規作成
out, err := os.Create(outFilePath)
if err != nil {
return fmt.Errorf("%w : %s", err, f.Name())
}

//変換する画像形式に応じてエンコードする
switch strings.ToLower(a.AfterFormat) {
case "jpg":
err = jpeg.Encode(out, img, &jpeg.Options{Quality: jpeg.DefaultQuality})
case "png":
err = png.Encode(out, img)
case "gif":
err = gif.Encode(out, img, &gif.Options{NumColors: 256, Quantizer: nil, Drawer: nil})
case "bmp":
err = bmp.Encode(out, img)
case "tiff":
err = tiff.Encode(out, img, &tiff.Options{Compression: 0, Predictor: true})
default:
return fmt.Errorf("The specified image format is not supported. : " + f.Name())
}

//エンコード時にエラーが返ってきていないかチェック
if err != nil {
return fmt.Errorf("%w : %s", err, out.Name())
}

if err := out.Close(); err != nil {
return fmt.Errorf("%w : %s", err, out.Name())
}

return nil

}
60 changes: 60 additions & 0 deletions kadai2/InoAyaka/converter/converter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package converter

import (
"fmt"
"testing"
)

func TestImageConverter(t *testing.T) {

var tests = []struct {
args Args
wantErr bool
want string
}{
{Args{FilePath: "../testdata/301_toJpg/_JR6xY.tiff", BeforeFormat: "tiff", AfterFormat: "jpg"},
false, ""},
{Args{FilePath: "../testdata/302_toPng/XvMdoh.bmp", BeforeFormat: "bmp", AfterFormat: "png"},
false, ""},
{Args{FilePath: "../testdata/303_toGif/gophercolor.png", BeforeFormat: "png", AfterFormat: "gif"},
false, ""},
{Args{FilePath: "../testdata/304_toBmp/XvMdoh.gif", BeforeFormat: "gif", AfterFormat: "bmp"},
false, ""},
{Args{FilePath: "../testdata/305_toTiff/vMfDls.jpg", BeforeFormat: "jpg", AfterFormat: "tiff"},
false, ""},

{Args{FilePath: "../testdata/391_notSupport/vMfDls.jpg", BeforeFormat: "jpg", AfterFormat: "HEIC"},
true, "The specified image format is not supported. : ../testdata/391_notSupport/vMfDls.jpg"},
{Args{FilePath: "../testdata/392_openError/vMfDls.jpg", BeforeFormat: "jpg", AfterFormat: "png"},
true, "open ../testdata/392_openError/vMfDls.jpg: no such file or directory"},
{Args{FilePath: "../testdata/393_decordError/notImage.jpg", BeforeFormat: "jpg", AfterFormat: "png"},
true, "image: unknown format : ../testdata/393_decordError/notImage.jpg"},
{Args{FilePath: "../testdata/394_createError/gophercolor.jpg", BeforeFormat: "jpg", AfterFormat: "png"},
true, "open ../testdata/394_createError/gophercolor.png: permission denied : ../testdata/394_createError/gophercolor.jpg"},
//{Args{FilePath: "../testdata/395_encordError", BeforeFormat: "jpg", AfterFormat: "png"},
// true, ""},
//{Args{FilePath: "../testdata/396_closeError", BeforeFormat: "jpg", AfterFormat: "png"},
// true, ""},
}

for _, test := range tests {
//失敗時にどのテストのどの引数で起きたのかを分かるようにする
descr := fmt.Sprintf("ImageConverter(%v)", test.args)

err := ImageConverter(test.args)

switch {
//エラー発生しないケースだが、エラーが発生した場合
case !test.wantErr && err != nil:
t.Errorf("want no err , %s = %q ", descr, err)
//エラーが発生するケースだが、エラーが発生しない場合
case test.wantErr && err == nil:
t.Errorf("want err , %s = %q ", descr, err)
//エラーが発生するケースで、エラー内容が異なる場合
case test.wantErr && err.Error() != test.want:
t.Errorf("%s = %q ,want %q", descr, err.Error(), test.want)

}

}
}
Loading