diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,16 +4,20 @@
 
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/).
 
-## Unreleased
+## 1.0.0.1 - 2025-10-24
 
-(no changes yet)
+### Changed
 
+- Split the test code into ordinary test and code generation test. The code generation test will not be run by default (by Hackage or Stackage, for example).
+
 ## 1.0.0.0 - 2025-10-24
 
 Initial release.
 
-- Added typeclasses `From` and `TryFrom`.
-- Added instances of `From` for some fundamental type-mappings in `base`:
+### Added
+
+- Typeclasses `From` and `TryFrom`.
+- Instances of `From` for some fundamental type-mappings in `base`:
     - All types in `Data.Int` and `Data.Word` can be both the source and the destination of the conversion.
     - The types `Float` and `Double` can be the destination, but not the source. So `from :: Int32 -> Float` exists, while `from :: Float -> Int32` does not.
     - That's it. We begin with minimal instances intentionally. For example, there is no `instance From Int String`. This is because it is tricky (often impossible) to selectively import instances, especially when the module dependency graph is complicated. We'd need to be careful about adding instances.
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -12,10 +12,15 @@
 
 ## Instances
 
-It is well known that it is difficult to "selectively" import/export typeclass instances. Therefore, we need to be careful about what instances to provide by default.
+It is difficult and often impossible to "selectively" import/export typeclass instances. Therefore, we need to be careful about what instances to provide by default.
 
-There are base functions, some of them even in `Prelude`, that basically serve as a less general version of `from`. Examples include `fromIntegral` and `fromEnum`. However, naively defining `instance (Integral a, Num b) => From a b` and `instance (Enum a) => From a Int` will quickly lead us to trouble:
+There are base functions, some of them even in `Prelude`, that basically serve as a less general version of `from`. Examples include `fromIntegral` and `fromEnum`. However, naively defining
 
+- `instance (Integral a, Num b) => From a b` and
+- `instance (Enum a) => From a Int`
+
+will quickly lead us to trouble:
+
 ```
     • Overlapping instances for From Int16 Int
         arising from a use of ‘from’
@@ -25,7 +30,7 @@
       ...
 ```
 
-Therefore, this package does not provide such "contextual" instances. (Of course, you may define them in your application project, if you want.)
+Therefore, this package does not provide such "contextual" instances.
 
 Instead, concrete instances are provided. For example, all pairs (excluding self to self) of these integral types are instantiated using `fromIntegral`:
 
diff --git a/codegen/Main.hs b/codegen/Main.hs
new file mode 100644
--- /dev/null
+++ b/codegen/Main.hs
@@ -0,0 +1,90 @@
+{-# LANGUAGE OverloadedStrings #-}
+
+module Main (main) where
+
+import Control.Exception
+import Data.ByteString (ByteString)
+import qualified Data.ByteString as B
+import Data.ByteString.Builder (Builder)
+import qualified Data.ByteString.Builder as B
+import RawFilePath
+import System.Exit
+import System.IO
+import System.Posix.Env.ByteString
+import System.Posix.Temp.ByteString
+
+srcTypes :: [ByteString]
+srcTypes =
+  [ "Int"
+  , "Integer"
+  , "Int8"
+  , "Int16"
+  , "Int32"
+  , "Int64"
+  , "Word8"
+  , "Word16"
+  , "Word32"
+  , "Word64"
+  ]
+
+dstTypes :: [ByteString]
+dstTypes =
+  [ "Int"
+  , "Integer"
+  , "Int8"
+  , "Int16"
+  , "Int32"
+  , "Int64"
+  , "Word8"
+  , "Word16"
+  , "Word32"
+  , "Word64"
+  , "Float"
+  , "Double"
+  ]
+
+main :: IO ()
+main = do
+  args <- getArgs
+  let shouldKeepFile = "--keep" `elem` args
+  bracket acquire (release shouldKeepFile) $ \(tmpPath, hdl) -> do
+    B.putStr $ tmpPath <> "\n"
+    B.hPutBuilder hdl $ header <> mconcat instancePart
+    hClose hdl
+    diffExitCode <-
+      runProcess "diff" ["-u", "--color=always", tmpPath, "src/From/Num.hs"]
+    case diffExitCode of
+      ExitSuccess -> return ()
+      _ -> exitWith diffExitCode
+ where
+  acquire = mkstemps "haskell-from-" ".hs"
+  release shouldKeepFile (path, hdl)
+    | shouldKeepFile = hClose hdl
+    | otherwise = hClose hdl >> removeFile path
+
+  runProcess cmd args = startProcess (proc cmd args) >>= waitForProcess
+
+  instanceLine src dst =
+    mconcat ["instance From ", B.byteString src, " ", B.byteString dst, " where\n"]
+  instancePart =
+    [ mconcat
+        [ "\n"
+        , "-- | Implementation is 'fromIntegral'\n"
+        , instanceLine src dst
+        , "  from = fromIntegral\n"
+        ]
+    | src <- srcTypes
+    , dst <- dstTypes
+    , src /= dst
+    ]
+
+header :: Builder
+header =
+  "{-# LANGUAGE MultiParamTypeClasses #-}\n\
+  \{-# OPTIONS_GHC -Wno-orphans #-}\n\
+  \\n\
+  \module From.Num () where\n\
+  \\n\
+  \import Data.Int\n\
+  \import Data.Word\n\
+  \import From.Classes\n"
diff --git a/from.cabal b/from.cabal
--- a/from.cabal
+++ b/from.cabal
@@ -5,7 +5,7 @@
 -- see: https://github.com/sol/hpack
 
 name:           from
-version:        1.0.0.0
+version:        1.0.0.1
 synopsis:       Typeclasses for type conversion mappings
 description:    This package provides the typeclasses 'From' and 'TryFrom'.
                 .
@@ -41,6 +41,11 @@
   type: git
   location: https://codeberg.org/xt/from
 
+flag codegen
+  description: Enable code generation test
+  manual: True
+  default: False
+
 library
   exposed-modules:
       From
@@ -55,17 +60,34 @@
       base >=4.7 && <5
   default-language: Haskell2010
 
-test-suite from-test
+test-suite codegen
   type: exitcode-stdio-1.0
   main-is: Main.hs
   other-modules:
       Paths_from
   hs-source-dirs:
+      codegen
+  ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
+  build-depends:
+      base >=4.7 && <5
+    , bytestring >=0.11.4.0 && <2
+    , rawfilepath >=1.0.1 && <2
+    , unix >2.7.3 && <3
+  default-language: Haskell2010
+  if flag(codegen)
+    buildable: True
+  else
+    buildable: False
+
+test-suite test
+  type: exitcode-stdio-1.0
+  main-is: Main.hs
+  other-modules:
+      Paths_from
+  hs-source-dirs:
       test
   ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints
   build-depends:
       base >=4.7 && <5
-    , bytestring
-    , rawfilepath
-    , unix
+    , from
   default-language: Haskell2010
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -1,90 +1,21 @@
-{-# LANGUAGE OverloadedStrings #-}
-
 module Main (main) where
 
-import Control.Exception
-import Data.ByteString (ByteString)
-import qualified Data.ByteString as B
-import Data.ByteString.Builder (Builder)
-import qualified Data.ByteString.Builder as B
-import RawFilePath
+import Data.Int
+import Data.Word
+import From
 import System.Exit
-import System.IO
-import System.Posix.Env.ByteString
-import System.Posix.Temp.ByteString
 
-srcTypes :: [ByteString]
-srcTypes =
-  [ "Int"
-  , "Integer"
-  , "Int8"
-  , "Int16"
-  , "Int32"
-  , "Int64"
-  , "Word8"
-  , "Word16"
-  , "Word32"
-  , "Word64"
-  ]
-
-dstTypes :: [ByteString]
-dstTypes =
-  [ "Int"
-  , "Integer"
-  , "Int8"
-  , "Int16"
-  , "Int32"
-  , "Int64"
-  , "Word8"
-  , "Word16"
-  , "Word32"
-  , "Word64"
-  , "Float"
-  , "Double"
-  ]
+assertEq :: (Eq term) => String -> term -> term -> IO ()
+assertEq comment leftTerm rightTerm
+  | leftTerm == rightTerm = report
+  | otherwise = report >> exitFailure
+ where
+  report = putStrLn comment
 
+-- TODO: More test cases
 main :: IO ()
 main = do
-  args <- getArgs
-  let shouldKeepFile = "--keep" `elem` args
-  bracket acquire (release shouldKeepFile) $ \(tmpPath, hdl) -> do
-    B.putStr $ tmpPath <> "\n"
-    B.hPutBuilder hdl $ header <> mconcat instancePart
-    hClose hdl
-    diffExitCode <-
-      runProcess "diff" ["-u", "--color=always", tmpPath, "src/From/Num.hs"]
-    case diffExitCode of
-      ExitSuccess -> return ()
-      _ -> exitWith diffExitCode
- where
-  acquire = mkstemps "haskell-from-" ".hs"
-  release shouldKeepFile (path, hdl)
-    | shouldKeepFile = hClose hdl
-    | otherwise = hClose hdl >> removeFile path
-
-  runProcess cmd args = startProcess (proc cmd args) >>= waitForProcess
-
-  instanceLine src dst =
-    mconcat ["instance From ", B.byteString src, " ", B.byteString dst, " where\n"]
-  instancePart =
-    [ mconcat
-        [ "\n"
-        , "-- | Implementation is 'fromIntegral'\n"
-        , instanceLine src dst
-        , "  from = fromIntegral\n"
-        ]
-    | src <- srcTypes
-    , dst <- dstTypes
-    , src /= dst
-    ]
-
-header :: Builder
-header =
-  "{-# LANGUAGE MultiParamTypeClasses #-}\n\
-  \{-# OPTIONS_GHC -Wno-orphans #-}\n\
-  \\n\
-  \module From.Num () where\n\
-  \\n\
-  \import Data.Int\n\
-  \import Data.Word\n\
-  \import From.Classes\n"
+  assertEq
+    "round trip from Int8 to Word32"
+    (0x11 :: Int8)
+    (from (from (0x11 :: Int8) :: Word32))
