SlideShare una empresa de Scribd logo
1 de 17
Testingの前の辺
   @kuchitama
テスト


• 不変で純粋な(副作用の無い)関数
• シンプルでテストしやすい
Mock

• Clojureだとわりと不要
• 不変コレクションやレコードは、シン
 プルなのでモックデータはいらないこ
 とが多い
でもMockりたいとき
• with-redefs
• 既に束縛されたvarを一時的に置き換え
•(def	 i	 1)
•(with-redefs	 [i	 3]	 i)
 ‣  3
•i	 
 ‣ 	 1 ←元に戻ってる
アサーション


• clojure/testのisマクロを利用
 -   (is (論理式) “アサーションメッセージ”)
is Sample
•   (require ‘clojure/test)

•   (is (= 1 2) “one is not two”)

    ‣   FAIL in clojure.lang.PersistentList$EmptyList@1
        (NO_SOURCE_FILE:17)

    ‣   one is not two ←アサーションメッセージ

    ‣   expected: (= 1 2)

    ‣    actual: (not (= 1 2))

    ‣   false
Error/Excptionの検査

• thrown? フォーム
• 第2引数の関数が第1引数で指定した
 throwableをthrowすればtrueを返す

• (thrown? (検出するthrowableクラス) (検
 査関数))
thrown? sample (1/2)


• (is (thrown? ArithmeticException (/ 1 0)))
 ‣ #<ArithmeticException
    java.lang.ArithmeticException: Divide by
    zero>
thrown? sample (2/2)
• (is (thrown-with-msg? ArithmeticException
  #"zero" (/ 1 0)))

 ‣ #<ArithmeticException
    java.lang.ArithmeticException: Divide by
    zero>
• 第2引数に正規表現を指定すると、エ
  ラーのメッセージにその表現が含まれ
  るかどうかまでテスト可能
test suite

• deftestで一連のテストをまとめて定義可
 能→名前を付けれる

• deftestで定義したtest suiteのmeta情報
 は:testに格納される
deftest sample
•   (deftest test-foo2
    (is (= 1 1) "one is not onw")
    (is (= 1 2) "one is not two"))
     ‣   #'user/test-foo2
•   ((:test (meta #'test-foo2)))
     ‣   FAIL in clojure.lang.PersistentList$EmptyList@1
         (NO_SOURCE_FILE:27)

     ‣   one is not two
     ‣   expected: (= 1 2)
     ‣    actual: (not (= 1 2))
     ‣   false
with-test
• プロダクトコードとテストコードをひ
 とまとまりに定義出来る

• プロダクトコードとして、テストとして
 それぞれで実行出来る

• ただし、テストコードの分までメモリ
 を圧迫するので注意
with-testサンプル(1/2)
•       (with-test
          (defn hello [name]
              (str "Hello, " name))
          (is (= hello "Brian") "Hello, Brian")
          (is (= (hello "Boo") "Hello, Foo" ) "hogehoge") )
         ‣  #'user/hello
    •    (run-tests)
         ‣  Testing user
         ‣  FAIL in (hello) (NO_SOURCE_FILE:32)
         ‣  Hello, Brian
         ‣  expected: (= hello "Brian")
         ‣   actual: (not (= #<user$eval56$hello__57 user
            $eval56$hello__57@23de4dd8> "Brian"))
with-testサンプル(2/2)
•       (with-test
          (defn hello [name]
              (str "Hello, " name))
          (is (= hello "Brian") "Hello, Brian")
          (is (= (hello "Boo") "Hello, Foo" ) "hogehoge") )
         ‣  #'user/hello
    •    (run-tests)
         ‣  Testing user
         ‣  FAIL in (hello) (NO_SOURCE_FILE:32)
         ‣  Hello, Brian
         ‣  expected: (= hello "Brian")
         ‣   actual: (not (= #<user$eval56$hello__57 user
            $eval56$hello__57@23de4dd8> "Brian"))
Fixtures(1/2)

• JUnitの@Before/@After 的なことを実現
 するテクニック

• 関数を引数にとるメソッドを定義して、
 事前条件と事後条件でくるむ
Fixtures(2/2)
• こんなかんじ
• (deftest hoge [f]
    ((before)
     (f)
      (after)))
Fixturesサンプル

• (defn fixtures-test [f]
     (let [n 3]
        (f n)))
• (fixtures-test #(* % 2))
   ‣6

Más contenido relacionado

La actualidad más candente

明日から使える Java SE 7
明日から使える Java SE 7明日から使える Java SE 7
明日から使える Java SE 7Yuichi Sakuraba
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説JPCERT Coordination Center
 
本当にあった怖い話し Db編
本当にあった怖い話し Db編本当にあった怖い話し Db編
本当にあった怖い話し Db編Oda Shinsuke
 
Functions
FunctionsFunctions
Functionsdo_aki
 
究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)fumoto kazuhiro
 
Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習JPCERT Coordination Center
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストYohei Sato
 
64ビット対応Dllインジェクション
64ビット対応Dllインジェクション64ビット対応Dllインジェクション
64ビット対応DllインジェクションShinichi Hirauchi
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門kwatch
 
SQLアンチパターン読書会 レジュメ
SQLアンチパターン読書会 レジュメSQLアンチパターン読書会 レジュメ
SQLアンチパターン読書会 レジュメMahito Ogura
 
Wpfと非同期
Wpfと非同期Wpfと非同期
Wpfと非同期yone64
 
第3回Webkit/HTML5勉強会 - File APIと加速度センサー
第3回Webkit/HTML5勉強会 - File APIと加速度センサー第3回Webkit/HTML5勉強会 - File APIと加速度センサー
第3回Webkit/HTML5勉強会 - File APIと加速度センサーnakamura001
 
New Generation Build System "Fly"
New Generation Build System "Fly"New Generation Build System "Fly"
New Generation Build System "Fly"deepblue will
 
「Html sql」で図書館hpにアクセスしてみよう
「Html sql」で図書館hpにアクセスしてみよう「Html sql」で図書館hpにアクセスしてみよう
「Html sql」で図書館hpにアクセスしてみようKentaro Matsui
 

La actualidad más candente (20)

mishimasyk#4
mishimasyk#4mishimasyk#4
mishimasyk#4
 
明日から使える Java SE 7
明日から使える Java SE 7明日から使える Java SE 7
明日から使える Java SE 7
 
131026 kansai-emacs
131026 kansai-emacs131026 kansai-emacs
131026 kansai-emacs
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説
 
本当にあった怖い話し Db編
本当にあった怖い話し Db編本当にあった怖い話し Db編
本当にあった怖い話し Db編
 
Functions
FunctionsFunctions
Functions
 
pecl-AOPの紹介
pecl-AOPの紹介pecl-AOPの紹介
pecl-AOPの紹介
 
究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)究極のバッチフレームワーク(予定)
究極のバッチフレームワーク(予定)
 
Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習
 
Tokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテストTokyor14 - R言語でユニットテスト
Tokyor14 - R言語でユニットテスト
 
64ビット対応Dllインジェクション
64ビット対応Dllインジェクション64ビット対応Dllインジェクション
64ビット対応Dllインジェクション
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門
 
emc++ chapter32
emc++ chapter32emc++ chapter32
emc++ chapter32
 
0x300
0x3000x300
0x300
 
SQLアンチパターン読書会 レジュメ
SQLアンチパターン読書会 レジュメSQLアンチパターン読書会 レジュメ
SQLアンチパターン読書会 レジュメ
 
Wpfと非同期
Wpfと非同期Wpfと非同期
Wpfと非同期
 
第3回Webkit/HTML5勉強会 - File APIと加速度センサー
第3回Webkit/HTML5勉強会 - File APIと加速度センサー第3回Webkit/HTML5勉強会 - File APIと加速度センサー
第3回Webkit/HTML5勉強会 - File APIと加速度センサー
 
New Generation Build System "Fly"
New Generation Build System "Fly"New Generation Build System "Fly"
New Generation Build System "Fly"
 
PHP language update 201211
PHP language update 201211PHP language update 201211
PHP language update 201211
 
「Html sql」で図書館hpにアクセスしてみよう
「Html sql」で図書館hpにアクセスしてみよう「Html sql」で図書館hpにアクセスしてみよう
「Html sql」で図書館hpにアクセスしてみよう
 

Similar a Clojrue 13 testing

Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2Masao Kato
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)Takuya Tsuchida
 
EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発Kentaro Ohkouchi
 
Introduction to Continuous Test Runner MakeGood
Introduction to Continuous Test Runner MakeGoodIntroduction to Continuous Test Runner MakeGood
Introduction to Continuous Test Runner MakeGoodAtsuhiro Kubo
 
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]David Buck
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1Susisu
 
Groovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようGroovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようAkira Shimosako
 
(call/cc (lambda (cont) (cont 知見)))
(call/cc (lambda (cont) (cont 知見)))(call/cc (lambda (cont) (cont 知見)))
(call/cc (lambda (cont) (cont 知見)))Susisu
 
ClassLoader Leak Patterns
ClassLoader Leak PatternsClassLoader Leak Patterns
ClassLoader Leak Patternsnekop
 
知って得する標準関数の使い方
知って得する標準関数の使い方知って得する標準関数の使い方
知って得する標準関数の使い方Soudai Sone
 
Elixirだ 第1回強化版 後半
Elixirだ 第1回強化版 後半Elixirだ 第1回強化版 後半
Elixirだ 第1回強化版 後半Joe_noh
 
JavaScriptクイックスタート
JavaScriptクイックスタートJavaScriptクイックスタート
JavaScriptクイックスタートShumpei Shiraishi
 
第5回勉強会
第5回勉強会第5回勉強会
第5回勉強会Mugen Fujii
 
CPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したいCPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したいcharsbar
 
PerlとSQLのいろいろ
PerlとSQLのいろいろPerlとSQLのいろいろ
PerlとSQLのいろいろTakuya Tsuchida
 
PHPフレームワーク入門
PHPフレームワーク入門PHPフレームワーク入門
PHPフレームワーク入門Sho A
 
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::UnitRuby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unithigaki
 

Similar a Clojrue 13 testing (20)

Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
 
EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発EC-CUBE + PHPUnit で 実践テスト駆動開発
EC-CUBE + PHPUnit で 実践テスト駆動開発
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
Introduction to Continuous Test Runner MakeGood
Introduction to Continuous Test Runner MakeGoodIntroduction to Continuous Test Runner MakeGood
Introduction to Continuous Test Runner MakeGood
 
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]
JDK 13 New Features [MeetUp with Java Experts! @Gaienmae/Dojima 2019]
 
JavaScript 講習会 #1
JavaScript 講習会 #1JavaScript 講習会 #1
JavaScript 講習会 #1
 
Aizu lt tokyo_luxion
Aizu lt tokyo_luxionAizu lt tokyo_luxion
Aizu lt tokyo_luxion
 
Groovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみようGroovyで楽にSQLを実行してみよう
Groovyで楽にSQLを実行してみよう
 
(call/cc (lambda (cont) (cont 知見)))
(call/cc (lambda (cont) (cont 知見)))(call/cc (lambda (cont) (cont 知見)))
(call/cc (lambda (cont) (cont 知見)))
 
Java7再入門講座
Java7再入門講座Java7再入門講座
Java7再入門講座
 
ClassLoader Leak Patterns
ClassLoader Leak PatternsClassLoader Leak Patterns
ClassLoader Leak Patterns
 
知って得する標準関数の使い方
知って得する標準関数の使い方知って得する標準関数の使い方
知って得する標準関数の使い方
 
Elixirだ 第1回強化版 後半
Elixirだ 第1回強化版 後半Elixirだ 第1回強化版 後半
Elixirだ 第1回強化版 後半
 
JavaScriptクイックスタート
JavaScriptクイックスタートJavaScriptクイックスタート
JavaScriptクイックスタート
 
第5回勉強会
第5回勉強会第5回勉強会
第5回勉強会
 
CPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したいCPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したい
 
PerlとSQLのいろいろ
PerlとSQLのいろいろPerlとSQLのいろいろ
PerlとSQLのいろいろ
 
PHPフレームワーク入門
PHPフレームワーク入門PHPフレームワーク入門
PHPフレームワーク入門
 
Ruby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::UnitRuby初級者向けレッスン 第46回 ─── Test::Unit
Ruby初級者向けレッスン 第46回 ─── Test::Unit
 

Más de Kiyotaka Kunihira

Mackerel Day#2 チェック監視が救う!!エンジニア0カンパニー
Mackerel Day#2 チェック監視が救う!!エンジニア0カンパニーMackerel Day#2 チェック監視が救う!!エンジニア0カンパニー
Mackerel Day#2 チェック監視が救う!!エンジニア0カンパニーKiyotaka Kunihira
 
着任したエンジニアをスムーズにテイクオフさせる道具だて
着任したエンジニアをスムーズにテイクオフさせる道具だて着任したエンジニアをスムーズにテイクオフさせる道具だて
着任したエンジニアをスムーズにテイクオフさせる道具だてKiyotaka Kunihira
 
ガチのスタートアップがScalaを採用した結果(公開版) #scala_ks
ガチのスタートアップがScalaを採用した結果(公開版) #scala_ksガチのスタートアップがScalaを採用した結果(公開版) #scala_ks
ガチのスタートアップがScalaを採用した結果(公開版) #scala_ksKiyotaka Kunihira
 
ここが変だよRuby/RoR #rubykansai
ここが変だよRuby/RoR #rubykansaiここが変だよRuby/RoR #rubykansai
ここが変だよRuby/RoR #rubykansaiKiyotaka Kunihira
 
時をかける開発 #devtool_night
時をかける開発 #devtool_night時をかける開発 #devtool_night
時をかける開発 #devtool_nightKiyotaka Kunihira
 
DevLove関西 - ShareWisの文化を支えるエンジニアリング
DevLove関西 - ShareWisの文化を支えるエンジニアリングDevLove関西 - ShareWisの文化を支えるエンジニアリング
DevLove関西 - ShareWisの文化を支えるエンジニアリングKiyotaka Kunihira
 
スタートアップとScala
スタートアップとScalaスタートアップとScala
スタートアップとScalaKiyotaka Kunihira
 
オリジナル社内ツールの末路
オリジナル社内ツールの末路オリジナル社内ツールの末路
オリジナル社内ツールの末路Kiyotaka Kunihira
 
GitBucketPlugin@2014忘年度会
GitBucketPlugin@2014忘年度会GitBucketPlugin@2014忘年度会
GitBucketPlugin@2014忘年度会Kiyotaka Kunihira
 
アジャイルな新婚旅行
アジャイルな新婚旅行アジャイルな新婚旅行
アジャイルな新婚旅行Kiyotaka Kunihira
 
もがいているエンジニア集まれ~今度こそ英語をモノにしよう~
もがいているエンジニア集まれ~今度こそ英語をモノにしよう~もがいているエンジニア集まれ~今度こそ英語をモノにしよう~
もがいているエンジニア集まれ~今度こそ英語をモノにしよう~Kiyotaka Kunihira
 
Scala開発チームの挑戦-技術編-@DevLove2014
Scala開発チームの挑戦-技術編-@DevLove2014Scala開発チームの挑戦-技術編-@DevLove2014
Scala開発チームの挑戦-技術編-@DevLove2014Kiyotaka Kunihira
 
気が狂わないサーバ増設x10
気が狂わないサーバ増設x10気が狂わないサーバ増設x10
気が狂わないサーバ増設x10Kiyotaka Kunihira
 
GitBucketで社内OSSしませんか?
GitBucketで社内OSSしませんか?GitBucketで社内OSSしませんか?
GitBucketで社内OSSしませんか?Kiyotaka Kunihira
 
仕事のゲーム化でやる気モードに変える
仕事のゲーム化でやる気モードに変える仕事のゲーム化でやる気モードに変える
仕事のゲーム化でやる気モードに変えるKiyotaka Kunihira
 
プログラマが 引っ越しで気をつける 3つのこと
プログラマが 引っ越しで気をつける 3つのことプログラマが 引っ越しで気をつける 3つのこと
プログラマが 引っ越しで気をつける 3つのことKiyotaka Kunihira
 
Chefとかプロビジョニングまわり
ChefとかプロビジョニングまわりChefとかプロビジョニングまわり
ChefとかプロビジョニングまわりKiyotaka Kunihira
 

Más de Kiyotaka Kunihira (20)

Mackerel Day#2 チェック監視が救う!!エンジニア0カンパニー
Mackerel Day#2 チェック監視が救う!!エンジニア0カンパニーMackerel Day#2 チェック監視が救う!!エンジニア0カンパニー
Mackerel Day#2 チェック監視が救う!!エンジニア0カンパニー
 
着任したエンジニアをスムーズにテイクオフさせる道具だて
着任したエンジニアをスムーズにテイクオフさせる道具だて着任したエンジニアをスムーズにテイクオフさせる道具だて
着任したエンジニアをスムーズにテイクオフさせる道具だて
 
React native実践談
React native実践談React native実践談
React native実践談
 
ガチのスタートアップがScalaを採用した結果(公開版) #scala_ks
ガチのスタートアップがScalaを採用した結果(公開版) #scala_ksガチのスタートアップがScalaを採用した結果(公開版) #scala_ks
ガチのスタートアップがScalaを採用した結果(公開版) #scala_ks
 
ここが変だよRuby/RoR #rubykansai
ここが変だよRuby/RoR #rubykansaiここが変だよRuby/RoR #rubykansai
ここが変だよRuby/RoR #rubykansai
 
時をかける開発 #devtool_night
時をかける開発 #devtool_night時をかける開発 #devtool_night
時をかける開発 #devtool_night
 
DevLove関西 - ShareWisの文化を支えるエンジニアリング
DevLove関西 - ShareWisの文化を支えるエンジニアリングDevLove関西 - ShareWisの文化を支えるエンジニアリング
DevLove関西 - ShareWisの文化を支えるエンジニアリング
 
スタートアップとScala
スタートアップとScalaスタートアップとScala
スタートアップとScala
 
オリジナル社内ツールの末路
オリジナル社内ツールの末路オリジナル社内ツールの末路
オリジナル社内ツールの末路
 
GitBucketPlugin@2014忘年度会
GitBucketPlugin@2014忘年度会GitBucketPlugin@2014忘年度会
GitBucketPlugin@2014忘年度会
 
アジャイルな新婚旅行
アジャイルな新婚旅行アジャイルな新婚旅行
アジャイルな新婚旅行
 
もがいているエンジニア集まれ~今度こそ英語をモノにしよう~
もがいているエンジニア集まれ~今度こそ英語をモノにしよう~もがいているエンジニア集まれ~今度こそ英語をモノにしよう~
もがいているエンジニア集まれ~今度こそ英語をモノにしよう~
 
とりあえず使えるSBT
とりあえず使えるSBTとりあえず使えるSBT
とりあえず使えるSBT
 
Scala開発チームの挑戦-技術編-@DevLove2014
Scala開発チームの挑戦-技術編-@DevLove2014Scala開発チームの挑戦-技術編-@DevLove2014
Scala開発チームの挑戦-技術編-@DevLove2014
 
気が狂わないサーバ増設x10
気が狂わないサーバ増設x10気が狂わないサーバ増設x10
気が狂わないサーバ増設x10
 
GitBucketで社内OSSしませんか?
GitBucketで社内OSSしませんか?GitBucketで社内OSSしませんか?
GitBucketで社内OSSしませんか?
 
仕事のゲーム化でやる気モードに変える
仕事のゲーム化でやる気モードに変える仕事のゲーム化でやる気モードに変える
仕事のゲーム化でやる気モードに変える
 
プログラマが 引っ越しで気をつける 3つのこと
プログラマが 引っ越しで気をつける 3つのことプログラマが 引っ越しで気をつける 3つのこと
プログラマが 引っ越しで気をつける 3つのこと
 
Ec2 automation framework
Ec2 automation frameworkEc2 automation framework
Ec2 automation framework
 
Chefとかプロビジョニングまわり
ChefとかプロビジョニングまわりChefとかプロビジョニングまわり
Chefとかプロビジョニングまわり
 

Clojrue 13 testing

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n